mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-19 09:55:26 +00:00
Consistent formatting for Dawn/Tint.
This CL updates the clang format files to have a single shared format between Dawn and Tint. The major changes are tabs are 4 spaces, lines are 100 columns and namespaces are not indented. Bug: dawn:1339 Change-Id: I4208742c95643998d9fd14e77a9cc558071ded39 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/87603 Commit-Queue: Dan Sinclair <dsinclair@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
73b1d1dafa
commit
41e4d9a34c
@@ -1,2 +0,0 @@
|
||||
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
BasedOnStyle: Chromium
|
||||
@@ -410,8 +410,8 @@ libtint_source_set("libtint_core_all_src") {
|
||||
"sem/pointer.h",
|
||||
"sem/reference.h",
|
||||
"sem/sampled_texture.h",
|
||||
"sem/sampler_texture_pair.h",
|
||||
"sem/sampler.h",
|
||||
"sem/sampler_texture_pair.h",
|
||||
"sem/storage_texture.h",
|
||||
"sem/switch_statement.h",
|
||||
"sem/texture.h",
|
||||
|
||||
@@ -17,25 +17,25 @@
|
||||
namespace tint::ast {
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Access access) {
|
||||
switch (access) {
|
||||
case ast::Access::kUndefined: {
|
||||
out << "undefined";
|
||||
break;
|
||||
switch (access) {
|
||||
case ast::Access::kUndefined: {
|
||||
out << "undefined";
|
||||
break;
|
||||
}
|
||||
case ast::Access::kRead: {
|
||||
out << "read";
|
||||
break;
|
||||
}
|
||||
case ast::Access::kReadWrite: {
|
||||
out << "read_write";
|
||||
break;
|
||||
}
|
||||
case ast::Access::kWrite: {
|
||||
out << "write";
|
||||
break;
|
||||
}
|
||||
}
|
||||
case ast::Access::kRead: {
|
||||
out << "read";
|
||||
break;
|
||||
}
|
||||
case ast::Access::kReadWrite: {
|
||||
out << "read_write";
|
||||
break;
|
||||
}
|
||||
case ast::Access::kWrite: {
|
||||
out << "write";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,16 +22,16 @@ namespace tint::ast {
|
||||
|
||||
/// The access control settings
|
||||
enum Access {
|
||||
/// Not declared in the source
|
||||
kUndefined = 0,
|
||||
/// Read only
|
||||
kRead,
|
||||
/// Write only
|
||||
kWrite,
|
||||
/// Read write
|
||||
kReadWrite,
|
||||
// Last valid access mode
|
||||
kLastValid = kReadWrite,
|
||||
/// Not declared in the source
|
||||
kUndefined = 0,
|
||||
/// Read only
|
||||
kRead,
|
||||
/// Write only
|
||||
kWrite,
|
||||
/// Read write
|
||||
kReadWrite,
|
||||
// Last valid access mode
|
||||
kLastValid = kReadWrite,
|
||||
};
|
||||
|
||||
/// @param out the std::ostream to write to
|
||||
|
||||
@@ -20,12 +20,9 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::Alias);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
Alias::Alias(ProgramID pid,
|
||||
const Source& src,
|
||||
const Symbol& n,
|
||||
const Type* subtype)
|
||||
Alias::Alias(ProgramID pid, const Source& src, const Symbol& n, const Type* subtype)
|
||||
: Base(pid, src, n), type(subtype) {
|
||||
TINT_ASSERT(AST, type);
|
||||
TINT_ASSERT(AST, type);
|
||||
}
|
||||
|
||||
Alias::Alias(Alias&&) = default;
|
||||
@@ -33,11 +30,11 @@ Alias::Alias(Alias&&) = default;
|
||||
Alias::~Alias() = default;
|
||||
|
||||
const Alias* Alias::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto sym = ctx->Clone(name);
|
||||
auto* ty = ctx->Clone(type);
|
||||
return ctx->dst->create<Alias>(src, sym, ty);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto sym = ctx->Clone(name);
|
||||
auto* ty = ctx->Clone(type);
|
||||
return ctx->dst->create<Alias>(src, sym, ty);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,28 +23,25 @@ namespace tint::ast {
|
||||
|
||||
/// A type alias type. Holds a name and pointer to another type.
|
||||
class Alias final : public Castable<Alias, TypeDecl> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param name the symbol for the alias
|
||||
/// @param subtype the alias'd type
|
||||
Alias(ProgramID pid,
|
||||
const Source& src,
|
||||
const Symbol& name,
|
||||
const Type* subtype);
|
||||
/// Move constructor
|
||||
Alias(Alias&&);
|
||||
/// Destructor
|
||||
~Alias() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param name the symbol for the alias
|
||||
/// @param subtype the alias'd type
|
||||
Alias(ProgramID pid, const Source& src, const Symbol& name, const Type* subtype);
|
||||
/// Move constructor
|
||||
Alias(Alias&&);
|
||||
/// Destructor
|
||||
~Alias() override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const Alias* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const Alias* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// the alias type
|
||||
const Type* const type;
|
||||
/// the alias type
|
||||
const Type* const type;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -33,10 +33,10 @@ namespace {
|
||||
using AstAliasTest = TestHelper;
|
||||
|
||||
TEST_F(AstAliasTest, Create) {
|
||||
auto* u32 = create<U32>();
|
||||
auto* a = Alias("a_type", u32);
|
||||
EXPECT_EQ(a->name, Symbol(1, ID()));
|
||||
EXPECT_EQ(a->type, u32);
|
||||
auto* u32 = create<U32>();
|
||||
auto* a = Alias("a_type", u32);
|
||||
EXPECT_EQ(a->name, Symbol(1, ID()));
|
||||
EXPECT_EQ(a->type, u32);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -24,17 +24,16 @@ namespace tint::ast {
|
||||
|
||||
namespace {
|
||||
// Returns the string representation of an array size expression.
|
||||
std::string SizeExprToString(const Expression* size,
|
||||
const SymbolTable& symbols) {
|
||||
if (auto* ident = size->As<IdentifierExpression>()) {
|
||||
return symbols.NameFor(ident->symbol);
|
||||
}
|
||||
if (auto* literal = size->As<IntLiteralExpression>()) {
|
||||
return std::to_string(literal->ValueAsU32());
|
||||
}
|
||||
// This will never be exposed to the user as the Resolver will reject this
|
||||
// expression for array size.
|
||||
return "<invalid>";
|
||||
std::string SizeExprToString(const Expression* size, const SymbolTable& symbols) {
|
||||
if (auto* ident = size->As<IdentifierExpression>()) {
|
||||
return symbols.NameFor(ident->symbol);
|
||||
}
|
||||
if (auto* literal = size->As<IntLiteralExpression>()) {
|
||||
return std::to_string(literal->ValueAsU32());
|
||||
}
|
||||
// This will never be exposed to the user as the Resolver will reject this
|
||||
// expression for array size.
|
||||
return "<invalid>";
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -50,27 +49,27 @@ Array::Array(Array&&) = default;
|
||||
Array::~Array() = default;
|
||||
|
||||
std::string Array::FriendlyName(const SymbolTable& symbols) const {
|
||||
std::ostringstream out;
|
||||
for (auto* attr : attributes) {
|
||||
if (auto* stride = attr->As<ast::StrideAttribute>()) {
|
||||
out << "@stride(" << stride->stride << ") ";
|
||||
std::ostringstream out;
|
||||
for (auto* attr : attributes) {
|
||||
if (auto* stride = attr->As<ast::StrideAttribute>()) {
|
||||
out << "@stride(" << stride->stride << ") ";
|
||||
}
|
||||
}
|
||||
}
|
||||
out << "array<" << type->FriendlyName(symbols);
|
||||
if (!IsRuntimeArray()) {
|
||||
out << ", " << SizeExprToString(count, symbols);
|
||||
}
|
||||
out << ">";
|
||||
return out.str();
|
||||
out << "array<" << type->FriendlyName(symbols);
|
||||
if (!IsRuntimeArray()) {
|
||||
out << ", " << SizeExprToString(count, symbols);
|
||||
}
|
||||
out << ">";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
const Array* Array::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* ty = ctx->Clone(type);
|
||||
auto* cnt = ctx->Clone(count);
|
||||
auto attrs = ctx->Clone(attributes);
|
||||
return ctx->dst->create<Array>(src, ty, cnt, attrs);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* ty = ctx->Clone(type);
|
||||
auto* cnt = ctx->Clone(count);
|
||||
auto attrs = ctx->Clone(attributes);
|
||||
return ctx->dst->create<Array>(src, ty, cnt, attrs);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -29,45 +29,45 @@ namespace tint::ast {
|
||||
|
||||
/// An array type. If size is zero then it is a runtime array.
|
||||
class Array final : public Castable<Array, Type> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param subtype the type of the array elements
|
||||
/// @param count the number of elements in the array. nullptr represents a
|
||||
/// runtime-sized array.
|
||||
/// @param attributes the array attributes
|
||||
Array(ProgramID pid,
|
||||
const Source& src,
|
||||
const Type* subtype,
|
||||
const Expression* count,
|
||||
AttributeList attributes);
|
||||
/// Move constructor
|
||||
Array(Array&&);
|
||||
~Array() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param subtype the type of the array elements
|
||||
/// @param count the number of elements in the array. nullptr represents a
|
||||
/// runtime-sized array.
|
||||
/// @param attributes the array attributes
|
||||
Array(ProgramID pid,
|
||||
const Source& src,
|
||||
const Type* subtype,
|
||||
const Expression* count,
|
||||
AttributeList attributes);
|
||||
/// Move constructor
|
||||
Array(Array&&);
|
||||
~Array() override;
|
||||
|
||||
/// @returns true if this is a runtime array.
|
||||
/// i.e. the size is determined at runtime
|
||||
bool IsRuntimeArray() const { return count == nullptr; }
|
||||
/// @returns true if this is a runtime array.
|
||||
/// i.e. the size is determined at runtime
|
||||
bool IsRuntimeArray() const { return count == nullptr; }
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const Array* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const Array* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// the array element type
|
||||
const Type* const type;
|
||||
/// the array element type
|
||||
const Type* const type;
|
||||
|
||||
/// the array size in elements, or nullptr for a runtime array
|
||||
const Expression* const count;
|
||||
/// the array size in elements, or nullptr for a runtime array
|
||||
const Expression* const count;
|
||||
|
||||
/// the array attributes
|
||||
const AttributeList attributes;
|
||||
/// the array attributes
|
||||
const AttributeList attributes;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,47 +22,46 @@ namespace {
|
||||
using AstArrayTest = TestHelper;
|
||||
|
||||
TEST_F(AstArrayTest, CreateSizedArray) {
|
||||
auto* u32 = create<U32>();
|
||||
auto* count = Expr(3);
|
||||
auto* arr = create<Array>(u32, count, AttributeList{});
|
||||
EXPECT_EQ(arr->type, u32);
|
||||
EXPECT_EQ(arr->count, count);
|
||||
EXPECT_TRUE(arr->Is<Array>());
|
||||
EXPECT_FALSE(arr->IsRuntimeArray());
|
||||
auto* u32 = create<U32>();
|
||||
auto* count = Expr(3);
|
||||
auto* arr = create<Array>(u32, count, AttributeList{});
|
||||
EXPECT_EQ(arr->type, u32);
|
||||
EXPECT_EQ(arr->count, count);
|
||||
EXPECT_TRUE(arr->Is<Array>());
|
||||
EXPECT_FALSE(arr->IsRuntimeArray());
|
||||
}
|
||||
|
||||
TEST_F(AstArrayTest, CreateRuntimeArray) {
|
||||
auto* u32 = create<U32>();
|
||||
auto* arr = create<Array>(u32, nullptr, AttributeList{});
|
||||
EXPECT_EQ(arr->type, u32);
|
||||
EXPECT_EQ(arr->count, nullptr);
|
||||
EXPECT_TRUE(arr->Is<Array>());
|
||||
EXPECT_TRUE(arr->IsRuntimeArray());
|
||||
auto* u32 = create<U32>();
|
||||
auto* arr = create<Array>(u32, nullptr, AttributeList{});
|
||||
EXPECT_EQ(arr->type, u32);
|
||||
EXPECT_EQ(arr->count, nullptr);
|
||||
EXPECT_TRUE(arr->Is<Array>());
|
||||
EXPECT_TRUE(arr->IsRuntimeArray());
|
||||
}
|
||||
|
||||
TEST_F(AstArrayTest, FriendlyName_RuntimeSized) {
|
||||
auto* i32 = create<I32>();
|
||||
auto* arr = create<Array>(i32, nullptr, AttributeList{});
|
||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32>");
|
||||
auto* i32 = create<I32>();
|
||||
auto* arr = create<Array>(i32, nullptr, AttributeList{});
|
||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32>");
|
||||
}
|
||||
|
||||
TEST_F(AstArrayTest, FriendlyName_LiteralSized) {
|
||||
auto* i32 = create<I32>();
|
||||
auto* arr = create<Array>(i32, Expr(5), AttributeList{});
|
||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, 5>");
|
||||
auto* i32 = create<I32>();
|
||||
auto* arr = create<Array>(i32, Expr(5), AttributeList{});
|
||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, 5>");
|
||||
}
|
||||
|
||||
TEST_F(AstArrayTest, FriendlyName_ConstantSized) {
|
||||
auto* i32 = create<I32>();
|
||||
auto* arr = create<Array>(i32, Expr("size"), AttributeList{});
|
||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, size>");
|
||||
auto* i32 = create<I32>();
|
||||
auto* arr = create<Array>(i32, Expr("size"), AttributeList{});
|
||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "array<i32, size>");
|
||||
}
|
||||
|
||||
TEST_F(AstArrayTest, FriendlyName_WithStride) {
|
||||
auto* i32 = create<I32>();
|
||||
auto* arr =
|
||||
create<Array>(i32, Expr(5), AttributeList{create<StrideAttribute>(32)});
|
||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "@stride(32) array<i32, 5>");
|
||||
auto* i32 = create<I32>();
|
||||
auto* arr = create<Array>(i32, Expr(5), AttributeList{create<StrideAttribute>(32)});
|
||||
EXPECT_EQ(arr->FriendlyName(Symbols()), "@stride(32) array<i32, 5>");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -25,10 +25,10 @@ AssignmentStatement::AssignmentStatement(ProgramID pid,
|
||||
const Expression* l,
|
||||
const Expression* r)
|
||||
: Base(pid, src), lhs(l), rhs(r) {
|
||||
TINT_ASSERT(AST, lhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
|
||||
TINT_ASSERT(AST, rhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id);
|
||||
TINT_ASSERT(AST, lhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
|
||||
TINT_ASSERT(AST, rhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id);
|
||||
}
|
||||
|
||||
AssignmentStatement::AssignmentStatement(AssignmentStatement&&) = default;
|
||||
@@ -36,11 +36,11 @@ AssignmentStatement::AssignmentStatement(AssignmentStatement&&) = default;
|
||||
AssignmentStatement::~AssignmentStatement() = default;
|
||||
|
||||
const AssignmentStatement* AssignmentStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* l = ctx->Clone(lhs);
|
||||
auto* r = ctx->Clone(rhs);
|
||||
return ctx->dst->create<AssignmentStatement>(src, l, r);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* l = ctx->Clone(lhs);
|
||||
auto* r = ctx->Clone(rhs);
|
||||
return ctx->dst->create<AssignmentStatement>(src, l, r);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -21,33 +21,32 @@
|
||||
namespace tint::ast {
|
||||
|
||||
/// An assignment statement
|
||||
class AssignmentStatement final
|
||||
: public Castable<AssignmentStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the assignment statement source
|
||||
/// @param lhs the left side of the expression
|
||||
/// @param rhs the right side of the expression
|
||||
AssignmentStatement(ProgramID program_id,
|
||||
const Source& source,
|
||||
const Expression* lhs,
|
||||
const Expression* rhs);
|
||||
/// Move constructor
|
||||
AssignmentStatement(AssignmentStatement&&);
|
||||
~AssignmentStatement() override;
|
||||
class AssignmentStatement final : public Castable<AssignmentStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the assignment statement source
|
||||
/// @param lhs the left side of the expression
|
||||
/// @param rhs the right side of the expression
|
||||
AssignmentStatement(ProgramID program_id,
|
||||
const Source& source,
|
||||
const Expression* lhs,
|
||||
const Expression* rhs);
|
||||
/// Move constructor
|
||||
AssignmentStatement(AssignmentStatement&&);
|
||||
~AssignmentStatement() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const AssignmentStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const AssignmentStatement* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// left side expression
|
||||
const Expression* const lhs;
|
||||
/// left side expression
|
||||
const Expression* const lhs;
|
||||
|
||||
/// right side expression
|
||||
const Expression* const rhs;
|
||||
/// right side expression
|
||||
const Expression* const rhs;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,69 +23,68 @@ namespace {
|
||||
using AssignmentStatementTest = TestHelper;
|
||||
|
||||
TEST_F(AssignmentStatementTest, Creation) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
|
||||
auto* stmt = create<AssignmentStatement>(lhs, rhs);
|
||||
EXPECT_EQ(stmt->lhs, lhs);
|
||||
EXPECT_EQ(stmt->rhs, rhs);
|
||||
auto* stmt = create<AssignmentStatement>(lhs, rhs);
|
||||
EXPECT_EQ(stmt->lhs, lhs);
|
||||
EXPECT_EQ(stmt->rhs, rhs);
|
||||
}
|
||||
|
||||
TEST_F(AssignmentStatementTest, CreationWithSource) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
|
||||
auto* stmt =
|
||||
create<AssignmentStatement>(Source{Source::Location{20, 2}}, lhs, rhs);
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* stmt = create<AssignmentStatement>(Source{Source::Location{20, 2}}, lhs, rhs);
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(AssignmentStatementTest, IsAssign) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
|
||||
auto* stmt = create<AssignmentStatement>(lhs, rhs);
|
||||
EXPECT_TRUE(stmt->Is<AssignmentStatement>());
|
||||
auto* stmt = create<AssignmentStatement>(lhs, rhs);
|
||||
EXPECT_TRUE(stmt->Is<AssignmentStatement>());
|
||||
}
|
||||
|
||||
TEST_F(AssignmentStatementTest, Assert_Null_LHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<AssignmentStatement>(nullptr, b.Expr(1));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<AssignmentStatement>(nullptr, b.Expr(1));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(AssignmentStatementTest, Assert_Null_RHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<AssignmentStatement>(b.Expr(1), nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<AssignmentStatement>(b.Expr(1), nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(AssignmentStatementTest, Assert_DifferentProgramID_LHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<AssignmentStatement>(b2.Expr("lhs"), b1.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<AssignmentStatement>(b2.Expr("lhs"), b1.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(AssignmentStatementTest, Assert_DifferentProgramID_RHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<AssignmentStatement>(b1.Expr("lhs"), b2.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<AssignmentStatement>(b1.Expr("lhs"), b2.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -24,9 +24,9 @@ Atomic::Atomic(ProgramID pid, const Source& src, const Type* const subtype)
|
||||
: Base(pid, src), type(subtype) {}
|
||||
|
||||
std::string Atomic::FriendlyName(const SymbolTable& symbols) const {
|
||||
std::ostringstream out;
|
||||
out << "atomic<" << type->FriendlyName(symbols) << ">";
|
||||
return out.str();
|
||||
std::ostringstream out;
|
||||
out << "atomic<" << type->FriendlyName(symbols) << ">";
|
||||
return out.str();
|
||||
}
|
||||
|
||||
Atomic::Atomic(Atomic&&) = default;
|
||||
@@ -34,10 +34,10 @@ Atomic::Atomic(Atomic&&) = default;
|
||||
Atomic::~Atomic() = default;
|
||||
|
||||
const Atomic* Atomic::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* ty = ctx->Clone(type);
|
||||
return ctx->dst->create<Atomic>(src, ty);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* ty = ctx->Clone(type);
|
||||
return ctx->dst->create<Atomic>(src, ty);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,28 +23,28 @@ namespace tint::ast {
|
||||
|
||||
/// An atomic type.
|
||||
class Atomic final : public Castable<Atomic, Type> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param subtype the pointee type
|
||||
Atomic(ProgramID pid, const Source& src, const Type* const subtype);
|
||||
/// Move constructor
|
||||
Atomic(Atomic&&);
|
||||
~Atomic() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param subtype the pointee type
|
||||
Atomic(ProgramID pid, const Source& src, const Type* const subtype);
|
||||
/// Move constructor
|
||||
Atomic(Atomic&&);
|
||||
~Atomic() override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const Atomic* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const Atomic* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// the pointee type
|
||||
const Type* const type;
|
||||
/// the pointee type
|
||||
const Type* const type;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,15 +23,15 @@ namespace {
|
||||
using AstAtomicTest = TestHelper;
|
||||
|
||||
TEST_F(AstAtomicTest, Creation) {
|
||||
auto* i32 = create<I32>();
|
||||
auto* p = create<Atomic>(i32);
|
||||
EXPECT_EQ(p->type, i32);
|
||||
auto* i32 = create<I32>();
|
||||
auto* p = create<Atomic>(i32);
|
||||
EXPECT_EQ(p->type, i32);
|
||||
}
|
||||
|
||||
TEST_F(AstAtomicTest, FriendlyName) {
|
||||
auto* i32 = create<I32>();
|
||||
auto* p = create<Atomic>(i32);
|
||||
EXPECT_EQ(p->FriendlyName(Symbols()), "atomic<i32>");
|
||||
auto* i32 = create<I32>();
|
||||
auto* p = create<Atomic>(i32);
|
||||
EXPECT_EQ(p->FriendlyName(Symbols()), "atomic<i32>");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -24,17 +24,17 @@ namespace tint::ast {
|
||||
|
||||
/// The base class for all attributes
|
||||
class Attribute : public Castable<Attribute, Node> {
|
||||
public:
|
||||
~Attribute() override;
|
||||
public:
|
||||
~Attribute() override;
|
||||
|
||||
/// @returns the WGSL name for the attribute
|
||||
virtual std::string Name() const = 0;
|
||||
/// @returns the WGSL name for the attribute
|
||||
virtual std::string Name() const = 0;
|
||||
|
||||
protected:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
Attribute(ProgramID pid, const Source& src) : Base(pid, src) {}
|
||||
protected:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
Attribute(ProgramID pid, const Source& src) : Base(pid, src) {}
|
||||
};
|
||||
|
||||
/// A list of attributes
|
||||
@@ -44,24 +44,24 @@ using AttributeList = std::vector<const Attribute*>;
|
||||
/// @returns true if `attributes` includes a attribute of type `T`
|
||||
template <typename T>
|
||||
bool HasAttribute(const AttributeList& attributes) {
|
||||
for (auto* attr : attributes) {
|
||||
if (attr->Is<T>()) {
|
||||
return true;
|
||||
for (auto* attr : attributes) {
|
||||
if (attr->Is<T>()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @param attributes the list of attributes to search
|
||||
/// @returns a pointer to `T` from `attributes` if found, otherwise nullptr.
|
||||
template <typename T>
|
||||
const T* GetAttribute(const AttributeList& attributes) {
|
||||
for (auto* attr : attributes) {
|
||||
if (attr->Is<T>()) {
|
||||
return attr->As<T>();
|
||||
for (auto* attr : attributes) {
|
||||
if (attr->Is<T>()) {
|
||||
return attr->As<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -26,11 +26,11 @@ BinaryExpression::BinaryExpression(ProgramID pid,
|
||||
const Expression* l,
|
||||
const Expression* r)
|
||||
: Base(pid, src), op(o), lhs(l), rhs(r) {
|
||||
TINT_ASSERT(AST, lhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
|
||||
TINT_ASSERT(AST, rhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id);
|
||||
TINT_ASSERT(AST, op != BinaryOp::kNone);
|
||||
TINT_ASSERT(AST, lhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
|
||||
TINT_ASSERT(AST, rhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id);
|
||||
TINT_ASSERT(AST, op != BinaryOp::kNone);
|
||||
}
|
||||
|
||||
BinaryExpression::BinaryExpression(BinaryExpression&&) = default;
|
||||
@@ -38,11 +38,11 @@ BinaryExpression::BinaryExpression(BinaryExpression&&) = default;
|
||||
BinaryExpression::~BinaryExpression() = default;
|
||||
|
||||
const BinaryExpression* BinaryExpression::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* l = ctx->Clone(lhs);
|
||||
auto* r = ctx->Clone(rhs);
|
||||
return ctx->dst->create<BinaryExpression>(src, op, l, r);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* l = ctx->Clone(lhs);
|
||||
auto* r = ctx->Clone(rhs);
|
||||
return ctx->dst->create<BinaryExpression>(src, op, l, r);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -21,240 +21,240 @@ namespace tint::ast {
|
||||
|
||||
/// The operator type
|
||||
enum class BinaryOp {
|
||||
kNone = 0,
|
||||
kAnd, // &
|
||||
kOr, // |
|
||||
kXor,
|
||||
kLogicalAnd, // &&
|
||||
kLogicalOr, // ||
|
||||
kEqual,
|
||||
kNotEqual,
|
||||
kLessThan,
|
||||
kGreaterThan,
|
||||
kLessThanEqual,
|
||||
kGreaterThanEqual,
|
||||
kShiftLeft,
|
||||
kShiftRight,
|
||||
kAdd,
|
||||
kSubtract,
|
||||
kMultiply,
|
||||
kDivide,
|
||||
kModulo,
|
||||
kNone = 0,
|
||||
kAnd, // &
|
||||
kOr, // |
|
||||
kXor,
|
||||
kLogicalAnd, // &&
|
||||
kLogicalOr, // ||
|
||||
kEqual,
|
||||
kNotEqual,
|
||||
kLessThan,
|
||||
kGreaterThan,
|
||||
kLessThanEqual,
|
||||
kGreaterThanEqual,
|
||||
kShiftLeft,
|
||||
kShiftRight,
|
||||
kAdd,
|
||||
kSubtract,
|
||||
kMultiply,
|
||||
kDivide,
|
||||
kModulo,
|
||||
};
|
||||
|
||||
/// An binary expression
|
||||
class BinaryExpression final : public Castable<BinaryExpression, Expression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the binary expression source
|
||||
/// @param op the operation type
|
||||
/// @param lhs the left side of the expression
|
||||
/// @param rhs the right side of the expression
|
||||
BinaryExpression(ProgramID program_id,
|
||||
const Source& source,
|
||||
BinaryOp op,
|
||||
const Expression* lhs,
|
||||
const Expression* rhs);
|
||||
/// Move constructor
|
||||
BinaryExpression(BinaryExpression&&);
|
||||
~BinaryExpression() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the binary expression source
|
||||
/// @param op the operation type
|
||||
/// @param lhs the left side of the expression
|
||||
/// @param rhs the right side of the expression
|
||||
BinaryExpression(ProgramID program_id,
|
||||
const Source& source,
|
||||
BinaryOp op,
|
||||
const Expression* lhs,
|
||||
const Expression* rhs);
|
||||
/// Move constructor
|
||||
BinaryExpression(BinaryExpression&&);
|
||||
~BinaryExpression() override;
|
||||
|
||||
/// @returns true if the op is and
|
||||
bool IsAnd() const { return op == BinaryOp::kAnd; }
|
||||
/// @returns true if the op is or
|
||||
bool IsOr() const { return op == BinaryOp::kOr; }
|
||||
/// @returns true if the op is xor
|
||||
bool IsXor() const { return op == BinaryOp::kXor; }
|
||||
/// @returns true if the op is logical and
|
||||
bool IsLogicalAnd() const { return op == BinaryOp::kLogicalAnd; }
|
||||
/// @returns true if the op is logical or
|
||||
bool IsLogicalOr() const { return op == BinaryOp::kLogicalOr; }
|
||||
/// @returns true if the op is equal
|
||||
bool IsEqual() const { return op == BinaryOp::kEqual; }
|
||||
/// @returns true if the op is not equal
|
||||
bool IsNotEqual() const { return op == BinaryOp::kNotEqual; }
|
||||
/// @returns true if the op is less than
|
||||
bool IsLessThan() const { return op == BinaryOp::kLessThan; }
|
||||
/// @returns true if the op is greater than
|
||||
bool IsGreaterThan() const { return op == BinaryOp::kGreaterThan; }
|
||||
/// @returns true if the op is less than equal
|
||||
bool IsLessThanEqual() const { return op == BinaryOp::kLessThanEqual; }
|
||||
/// @returns true if the op is greater than equal
|
||||
bool IsGreaterThanEqual() const { return op == BinaryOp::kGreaterThanEqual; }
|
||||
/// @returns true if the op is shift left
|
||||
bool IsShiftLeft() const { return op == BinaryOp::kShiftLeft; }
|
||||
/// @returns true if the op is shift right
|
||||
bool IsShiftRight() const { return op == BinaryOp::kShiftRight; }
|
||||
/// @returns true if the op is add
|
||||
bool IsAdd() const { return op == BinaryOp::kAdd; }
|
||||
/// @returns true if the op is subtract
|
||||
bool IsSubtract() const { return op == BinaryOp::kSubtract; }
|
||||
/// @returns true if the op is multiply
|
||||
bool IsMultiply() const { return op == BinaryOp::kMultiply; }
|
||||
/// @returns true if the op is divide
|
||||
bool IsDivide() const { return op == BinaryOp::kDivide; }
|
||||
/// @returns true if the op is modulo
|
||||
bool IsModulo() const { return op == BinaryOp::kModulo; }
|
||||
/// @returns true if the op is an arithmetic operation
|
||||
bool IsArithmetic() const;
|
||||
/// @returns true if the op is a comparison operation
|
||||
bool IsComparison() const;
|
||||
/// @returns true if the op is a bitwise operation
|
||||
bool IsBitwise() const;
|
||||
/// @returns true if the op is a bit shift operation
|
||||
bool IsBitshift() const;
|
||||
/// @returns true if the op is a logical expression
|
||||
bool IsLogical() const;
|
||||
/// @returns true if the op is and
|
||||
bool IsAnd() const { return op == BinaryOp::kAnd; }
|
||||
/// @returns true if the op is or
|
||||
bool IsOr() const { return op == BinaryOp::kOr; }
|
||||
/// @returns true if the op is xor
|
||||
bool IsXor() const { return op == BinaryOp::kXor; }
|
||||
/// @returns true if the op is logical and
|
||||
bool IsLogicalAnd() const { return op == BinaryOp::kLogicalAnd; }
|
||||
/// @returns true if the op is logical or
|
||||
bool IsLogicalOr() const { return op == BinaryOp::kLogicalOr; }
|
||||
/// @returns true if the op is equal
|
||||
bool IsEqual() const { return op == BinaryOp::kEqual; }
|
||||
/// @returns true if the op is not equal
|
||||
bool IsNotEqual() const { return op == BinaryOp::kNotEqual; }
|
||||
/// @returns true if the op is less than
|
||||
bool IsLessThan() const { return op == BinaryOp::kLessThan; }
|
||||
/// @returns true if the op is greater than
|
||||
bool IsGreaterThan() const { return op == BinaryOp::kGreaterThan; }
|
||||
/// @returns true if the op is less than equal
|
||||
bool IsLessThanEqual() const { return op == BinaryOp::kLessThanEqual; }
|
||||
/// @returns true if the op is greater than equal
|
||||
bool IsGreaterThanEqual() const { return op == BinaryOp::kGreaterThanEqual; }
|
||||
/// @returns true if the op is shift left
|
||||
bool IsShiftLeft() const { return op == BinaryOp::kShiftLeft; }
|
||||
/// @returns true if the op is shift right
|
||||
bool IsShiftRight() const { return op == BinaryOp::kShiftRight; }
|
||||
/// @returns true if the op is add
|
||||
bool IsAdd() const { return op == BinaryOp::kAdd; }
|
||||
/// @returns true if the op is subtract
|
||||
bool IsSubtract() const { return op == BinaryOp::kSubtract; }
|
||||
/// @returns true if the op is multiply
|
||||
bool IsMultiply() const { return op == BinaryOp::kMultiply; }
|
||||
/// @returns true if the op is divide
|
||||
bool IsDivide() const { return op == BinaryOp::kDivide; }
|
||||
/// @returns true if the op is modulo
|
||||
bool IsModulo() const { return op == BinaryOp::kModulo; }
|
||||
/// @returns true if the op is an arithmetic operation
|
||||
bool IsArithmetic() const;
|
||||
/// @returns true if the op is a comparison operation
|
||||
bool IsComparison() const;
|
||||
/// @returns true if the op is a bitwise operation
|
||||
bool IsBitwise() const;
|
||||
/// @returns true if the op is a bit shift operation
|
||||
bool IsBitshift() const;
|
||||
/// @returns true if the op is a logical expression
|
||||
bool IsLogical() const;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BinaryExpression* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BinaryExpression* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// the binary op type
|
||||
const BinaryOp op;
|
||||
/// the left side expression
|
||||
const Expression* const lhs;
|
||||
/// the right side expression
|
||||
const Expression* const rhs;
|
||||
/// the binary op type
|
||||
const BinaryOp op;
|
||||
/// the left side expression
|
||||
const Expression* const lhs;
|
||||
/// the right side expression
|
||||
const Expression* const rhs;
|
||||
};
|
||||
|
||||
/// @param op the operator
|
||||
/// @returns true if the op is an arithmetic operation
|
||||
inline bool IsArithmetic(BinaryOp op) {
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kAdd:
|
||||
case ast::BinaryOp::kSubtract:
|
||||
case ast::BinaryOp::kMultiply:
|
||||
case ast::BinaryOp::kDivide:
|
||||
case ast::BinaryOp::kModulo:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kAdd:
|
||||
case ast::BinaryOp::kSubtract:
|
||||
case ast::BinaryOp::kMultiply:
|
||||
case ast::BinaryOp::kDivide:
|
||||
case ast::BinaryOp::kModulo:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// @param op the operator
|
||||
/// @returns true if the op is a comparison operation
|
||||
inline bool IsComparison(BinaryOp op) {
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kEqual:
|
||||
case ast::BinaryOp::kNotEqual:
|
||||
case ast::BinaryOp::kLessThan:
|
||||
case ast::BinaryOp::kLessThanEqual:
|
||||
case ast::BinaryOp::kGreaterThan:
|
||||
case ast::BinaryOp::kGreaterThanEqual:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kEqual:
|
||||
case ast::BinaryOp::kNotEqual:
|
||||
case ast::BinaryOp::kLessThan:
|
||||
case ast::BinaryOp::kLessThanEqual:
|
||||
case ast::BinaryOp::kGreaterThan:
|
||||
case ast::BinaryOp::kGreaterThanEqual:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// @param op the operator
|
||||
/// @returns true if the op is a bitwise operation
|
||||
inline bool IsBitwise(BinaryOp op) {
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kAnd:
|
||||
case ast::BinaryOp::kOr:
|
||||
case ast::BinaryOp::kXor:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kAnd:
|
||||
case ast::BinaryOp::kOr:
|
||||
case ast::BinaryOp::kXor:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// @param op the operator
|
||||
/// @returns true if the op is a bit shift operation
|
||||
inline bool IsBitshift(BinaryOp op) {
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kShiftLeft:
|
||||
case ast::BinaryOp::kShiftRight:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kShiftLeft:
|
||||
case ast::BinaryOp::kShiftRight:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool BinaryExpression::IsLogical() const {
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kLogicalAnd:
|
||||
case ast::BinaryOp::kLogicalOr:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
switch (op) {
|
||||
case ast::BinaryOp::kLogicalAnd:
|
||||
case ast::BinaryOp::kLogicalOr:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool BinaryExpression::IsArithmetic() const {
|
||||
return ast::IsArithmetic(op);
|
||||
return ast::IsArithmetic(op);
|
||||
}
|
||||
|
||||
inline bool BinaryExpression::IsComparison() const {
|
||||
return ast::IsComparison(op);
|
||||
return ast::IsComparison(op);
|
||||
}
|
||||
|
||||
inline bool BinaryExpression::IsBitwise() const {
|
||||
return ast::IsBitwise(op);
|
||||
return ast::IsBitwise(op);
|
||||
}
|
||||
|
||||
inline bool BinaryExpression::IsBitshift() const {
|
||||
return ast::IsBitshift(op);
|
||||
return ast::IsBitshift(op);
|
||||
}
|
||||
|
||||
/// @returns the human readable name of the given BinaryOp
|
||||
/// @param op the BinaryOp
|
||||
constexpr const char* FriendlyName(BinaryOp op) {
|
||||
switch (op) {
|
||||
case BinaryOp::kNone:
|
||||
return "none";
|
||||
case BinaryOp::kAnd:
|
||||
return "and";
|
||||
case BinaryOp::kOr:
|
||||
return "or";
|
||||
case BinaryOp::kXor:
|
||||
return "xor";
|
||||
case BinaryOp::kLogicalAnd:
|
||||
return "logical_and";
|
||||
case BinaryOp::kLogicalOr:
|
||||
return "logical_or";
|
||||
case BinaryOp::kEqual:
|
||||
return "equal";
|
||||
case BinaryOp::kNotEqual:
|
||||
return "not_equal";
|
||||
case BinaryOp::kLessThan:
|
||||
return "less_than";
|
||||
case BinaryOp::kGreaterThan:
|
||||
return "greater_than";
|
||||
case BinaryOp::kLessThanEqual:
|
||||
return "less_than_equal";
|
||||
case BinaryOp::kGreaterThanEqual:
|
||||
return "greater_than_equal";
|
||||
case BinaryOp::kShiftLeft:
|
||||
return "shift_left";
|
||||
case BinaryOp::kShiftRight:
|
||||
return "shift_right";
|
||||
case BinaryOp::kAdd:
|
||||
return "add";
|
||||
case BinaryOp::kSubtract:
|
||||
return "subtract";
|
||||
case BinaryOp::kMultiply:
|
||||
return "multiply";
|
||||
case BinaryOp::kDivide:
|
||||
return "divide";
|
||||
case BinaryOp::kModulo:
|
||||
return "modulo";
|
||||
}
|
||||
return "INVALID";
|
||||
switch (op) {
|
||||
case BinaryOp::kNone:
|
||||
return "none";
|
||||
case BinaryOp::kAnd:
|
||||
return "and";
|
||||
case BinaryOp::kOr:
|
||||
return "or";
|
||||
case BinaryOp::kXor:
|
||||
return "xor";
|
||||
case BinaryOp::kLogicalAnd:
|
||||
return "logical_and";
|
||||
case BinaryOp::kLogicalOr:
|
||||
return "logical_or";
|
||||
case BinaryOp::kEqual:
|
||||
return "equal";
|
||||
case BinaryOp::kNotEqual:
|
||||
return "not_equal";
|
||||
case BinaryOp::kLessThan:
|
||||
return "less_than";
|
||||
case BinaryOp::kGreaterThan:
|
||||
return "greater_than";
|
||||
case BinaryOp::kLessThanEqual:
|
||||
return "less_than_equal";
|
||||
case BinaryOp::kGreaterThanEqual:
|
||||
return "greater_than_equal";
|
||||
case BinaryOp::kShiftLeft:
|
||||
return "shift_left";
|
||||
case BinaryOp::kShiftRight:
|
||||
return "shift_right";
|
||||
case BinaryOp::kAdd:
|
||||
return "add";
|
||||
case BinaryOp::kSubtract:
|
||||
return "subtract";
|
||||
case BinaryOp::kMultiply:
|
||||
return "multiply";
|
||||
case BinaryOp::kDivide:
|
||||
return "divide";
|
||||
case BinaryOp::kModulo:
|
||||
return "modulo";
|
||||
}
|
||||
return "INVALID";
|
||||
}
|
||||
|
||||
/// @param out the std::ostream to write to
|
||||
/// @param op the BinaryOp
|
||||
/// @return the std::ostream so calls can be chained
|
||||
inline std::ostream& operator<<(std::ostream& out, BinaryOp op) {
|
||||
out << FriendlyName(op);
|
||||
return out;
|
||||
out << FriendlyName(op);
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -21,72 +21,69 @@ namespace {
|
||||
using BinaryExpressionTest = TestHelper;
|
||||
|
||||
TEST_F(BinaryExpressionTest, Creation) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
|
||||
auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
|
||||
EXPECT_EQ(r->lhs, lhs);
|
||||
EXPECT_EQ(r->rhs, rhs);
|
||||
EXPECT_EQ(r->op, BinaryOp::kEqual);
|
||||
auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
|
||||
EXPECT_EQ(r->lhs, lhs);
|
||||
EXPECT_EQ(r->rhs, rhs);
|
||||
EXPECT_EQ(r->op, BinaryOp::kEqual);
|
||||
}
|
||||
|
||||
TEST_F(BinaryExpressionTest, Creation_WithSource) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
|
||||
auto* r = create<BinaryExpression>(Source{Source::Location{20, 2}},
|
||||
BinaryOp::kEqual, lhs, rhs);
|
||||
auto src = r->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* r = create<BinaryExpression>(Source{Source::Location{20, 2}}, BinaryOp::kEqual, lhs, rhs);
|
||||
auto src = r->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(BinaryExpressionTest, IsBinary) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
|
||||
auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
|
||||
EXPECT_TRUE(r->Is<BinaryExpression>());
|
||||
auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
|
||||
EXPECT_TRUE(r->Is<BinaryExpression>());
|
||||
}
|
||||
|
||||
TEST_F(BinaryExpressionTest, Assert_Null_LHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BinaryExpression>(BinaryOp::kEqual, nullptr, b.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BinaryExpression>(BinaryOp::kEqual, nullptr, b.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(BinaryExpressionTest, Assert_Null_RHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BinaryExpression>(BinaryOp::kEqual, b.Expr("lhs"), nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BinaryExpression>(BinaryOp::kEqual, b.Expr("lhs"), nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(BinaryExpressionTest, Assert_DifferentProgramID_LHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BinaryExpression>(BinaryOp::kEqual, b2.Expr("lhs"),
|
||||
b1.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BinaryExpression>(BinaryOp::kEqual, b2.Expr("lhs"), b1.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(BinaryExpressionTest, Assert_DifferentProgramID_RHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BinaryExpression>(BinaryOp::kEqual, b1.Expr("lhs"),
|
||||
b2.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BinaryExpression>(BinaryOp::kEqual, b1.Expr("lhs"), b2.Expr("rhs"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -22,21 +22,19 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::BindingAttribute);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
BindingAttribute::BindingAttribute(ProgramID pid,
|
||||
const Source& src,
|
||||
uint32_t val)
|
||||
BindingAttribute::BindingAttribute(ProgramID pid, const Source& src, uint32_t val)
|
||||
: Base(pid, src), value(val) {}
|
||||
|
||||
BindingAttribute::~BindingAttribute() = default;
|
||||
|
||||
std::string BindingAttribute::Name() const {
|
||||
return "binding";
|
||||
return "binding";
|
||||
}
|
||||
|
||||
const BindingAttribute* BindingAttribute::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<BindingAttribute>(src, value);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<BindingAttribute>(src, value);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,25 +23,25 @@ namespace tint::ast {
|
||||
|
||||
/// A binding attribute
|
||||
class BindingAttribute final : public Castable<BindingAttribute, Attribute> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param value the binding value
|
||||
BindingAttribute(ProgramID pid, const Source& src, uint32_t value);
|
||||
~BindingAttribute() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param value the binding value
|
||||
BindingAttribute(ProgramID pid, const Source& src, uint32_t value);
|
||||
~BindingAttribute() override;
|
||||
|
||||
/// @returns the WGSL name for the attribute
|
||||
std::string Name() const override;
|
||||
/// @returns the WGSL name for the attribute
|
||||
std::string Name() const override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BindingAttribute* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BindingAttribute* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// the binding value
|
||||
const uint32_t value;
|
||||
/// the binding value
|
||||
const uint32_t value;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace {
|
||||
using BindingAttributeTest = TestHelper;
|
||||
|
||||
TEST_F(BindingAttributeTest, Creation) {
|
||||
auto* d = create<BindingAttribute>(2);
|
||||
EXPECT_EQ(2u, d->value);
|
||||
auto* d = create<BindingAttribute>(2);
|
||||
EXPECT_EQ(2u, d->value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -25,20 +25,20 @@ BitcastExpression::BitcastExpression(ProgramID pid,
|
||||
const Type* t,
|
||||
const Expression* e)
|
||||
: Base(pid, src), type(t), expr(e) {
|
||||
TINT_ASSERT(AST, type);
|
||||
TINT_ASSERT(AST, expr);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr, program_id);
|
||||
TINT_ASSERT(AST, type);
|
||||
TINT_ASSERT(AST, expr);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr, program_id);
|
||||
}
|
||||
|
||||
BitcastExpression::BitcastExpression(BitcastExpression&&) = default;
|
||||
BitcastExpression::~BitcastExpression() = default;
|
||||
|
||||
const BitcastExpression* BitcastExpression::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* t = ctx->Clone(type);
|
||||
auto* e = ctx->Clone(expr);
|
||||
return ctx->dst->create<BitcastExpression>(src, t, e);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* t = ctx->Clone(type);
|
||||
auto* e = ctx->Clone(expr);
|
||||
return ctx->dst->create<BitcastExpression>(src, t, e);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -26,30 +26,30 @@ namespace tint::ast {
|
||||
|
||||
/// A bitcast expression
|
||||
class BitcastExpression final : public Castable<BitcastExpression, Expression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the bitcast expression source
|
||||
/// @param type the type
|
||||
/// @param expr the expr
|
||||
BitcastExpression(ProgramID program_id,
|
||||
const Source& source,
|
||||
const Type* type,
|
||||
const Expression* expr);
|
||||
/// Move constructor
|
||||
BitcastExpression(BitcastExpression&&);
|
||||
~BitcastExpression() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the bitcast expression source
|
||||
/// @param type the type
|
||||
/// @param expr the expr
|
||||
BitcastExpression(ProgramID program_id,
|
||||
const Source& source,
|
||||
const Type* type,
|
||||
const Expression* expr);
|
||||
/// Move constructor
|
||||
BitcastExpression(BitcastExpression&&);
|
||||
~BitcastExpression() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BitcastExpression* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BitcastExpression* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// the target cast type
|
||||
const Type* const type;
|
||||
/// the expression
|
||||
const Expression* const expr;
|
||||
/// the target cast type
|
||||
const Type* const type;
|
||||
/// the expression
|
||||
const Expression* const expr;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,56 +23,55 @@ namespace {
|
||||
using BitcastExpressionTest = TestHelper;
|
||||
|
||||
TEST_F(BitcastExpressionTest, Create) {
|
||||
auto* expr = Expr("expr");
|
||||
auto* expr = Expr("expr");
|
||||
|
||||
auto* exp = create<BitcastExpression>(ty.f32(), expr);
|
||||
EXPECT_TRUE(exp->type->Is<ast::F32>());
|
||||
ASSERT_EQ(exp->expr, expr);
|
||||
auto* exp = create<BitcastExpression>(ty.f32(), expr);
|
||||
EXPECT_TRUE(exp->type->Is<ast::F32>());
|
||||
ASSERT_EQ(exp->expr, expr);
|
||||
}
|
||||
|
||||
TEST_F(BitcastExpressionTest, CreateWithSource) {
|
||||
auto* expr = Expr("expr");
|
||||
auto* expr = Expr("expr");
|
||||
|
||||
auto* exp = create<BitcastExpression>(Source{Source::Location{20, 2}},
|
||||
ty.f32(), expr);
|
||||
auto src = exp->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* exp = create<BitcastExpression>(Source{Source::Location{20, 2}}, ty.f32(), expr);
|
||||
auto src = exp->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(BitcastExpressionTest, IsBitcast) {
|
||||
auto* expr = Expr("expr");
|
||||
auto* expr = Expr("expr");
|
||||
|
||||
auto* exp = create<BitcastExpression>(ty.f32(), expr);
|
||||
EXPECT_TRUE(exp->Is<BitcastExpression>());
|
||||
auto* exp = create<BitcastExpression>(ty.f32(), expr);
|
||||
EXPECT_TRUE(exp->Is<BitcastExpression>());
|
||||
}
|
||||
|
||||
TEST_F(BitcastExpressionTest, Assert_Null_Type) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BitcastExpression>(nullptr, b.Expr("idx"));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BitcastExpression>(nullptr, b.Expr("idx"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(BitcastExpressionTest, Assert_Null_Expr) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BitcastExpression>(b.ty.f32(), nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BitcastExpression>(b.ty.f32(), nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(BitcastExpressionTest, Assert_DifferentProgramID_Expr) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BitcastExpression>(b1.ty.f32(), b2.Expr("idx"));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BitcastExpression>(b1.ty.f32(), b2.Expr("idx"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -20,14 +20,12 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::BlockStatement);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
BlockStatement::BlockStatement(ProgramID pid,
|
||||
const Source& src,
|
||||
const StatementList& stmts)
|
||||
BlockStatement::BlockStatement(ProgramID pid, const Source& src, const StatementList& stmts)
|
||||
: Base(pid, src), statements(std::move(stmts)) {
|
||||
for (auto* stmt : statements) {
|
||||
TINT_ASSERT(AST, stmt);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
|
||||
}
|
||||
for (auto* stmt : statements) {
|
||||
TINT_ASSERT(AST, stmt);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
|
||||
}
|
||||
}
|
||||
|
||||
BlockStatement::BlockStatement(BlockStatement&&) = default;
|
||||
@@ -35,10 +33,10 @@ BlockStatement::BlockStatement(BlockStatement&&) = default;
|
||||
BlockStatement::~BlockStatement() = default;
|
||||
|
||||
const BlockStatement* BlockStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto stmts = ctx->Clone(statements);
|
||||
return ctx->dst->create<BlockStatement>(src, stmts);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto stmts = ctx->Clone(statements);
|
||||
return ctx->dst->create<BlockStatement>(src, stmts);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,34 +23,30 @@ namespace tint::ast {
|
||||
|
||||
/// A block statement
|
||||
class BlockStatement final : public Castable<BlockStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the block statement source
|
||||
/// @param statements the statements
|
||||
BlockStatement(ProgramID program_id,
|
||||
const Source& source,
|
||||
const StatementList& statements);
|
||||
/// Move constructor
|
||||
BlockStatement(BlockStatement&&);
|
||||
~BlockStatement() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the block statement source
|
||||
/// @param statements the statements
|
||||
BlockStatement(ProgramID program_id, const Source& source, const StatementList& statements);
|
||||
/// Move constructor
|
||||
BlockStatement(BlockStatement&&);
|
||||
~BlockStatement() override;
|
||||
|
||||
/// @returns true if the block has no statements
|
||||
bool Empty() const { return statements.empty(); }
|
||||
/// @returns true if the block has no statements
|
||||
bool Empty() const { return statements.empty(); }
|
||||
|
||||
/// @returns the last statement in the block or nullptr if block empty
|
||||
const Statement* Last() const {
|
||||
return statements.empty() ? nullptr : statements.back();
|
||||
}
|
||||
/// @returns the last statement in the block or nullptr if block empty
|
||||
const Statement* Last() const { return statements.empty() ? nullptr : statements.back(); }
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BlockStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BlockStatement* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// the statement list
|
||||
const StatementList statements;
|
||||
/// the statement list
|
||||
const StatementList statements;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,46 +23,44 @@ namespace {
|
||||
using BlockStatementTest = TestHelper;
|
||||
|
||||
TEST_F(BlockStatementTest, Creation) {
|
||||
auto* d = create<DiscardStatement>();
|
||||
auto* ptr = d;
|
||||
auto* d = create<DiscardStatement>();
|
||||
auto* ptr = d;
|
||||
|
||||
auto* b = create<BlockStatement>(StatementList{d});
|
||||
auto* b = create<BlockStatement>(StatementList{d});
|
||||
|
||||
ASSERT_EQ(b->statements.size(), 1u);
|
||||
EXPECT_EQ(b->statements[0], ptr);
|
||||
ASSERT_EQ(b->statements.size(), 1u);
|
||||
EXPECT_EQ(b->statements[0], ptr);
|
||||
}
|
||||
|
||||
TEST_F(BlockStatementTest, Creation_WithSource) {
|
||||
auto* b = create<BlockStatement>(Source{Source::Location{20, 2}},
|
||||
ast::StatementList{});
|
||||
auto src = b->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* b = create<BlockStatement>(Source{Source::Location{20, 2}}, ast::StatementList{});
|
||||
auto src = b->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(BlockStatementTest, IsBlock) {
|
||||
auto* b = create<BlockStatement>(ast::StatementList{});
|
||||
EXPECT_TRUE(b->Is<BlockStatement>());
|
||||
auto* b = create<BlockStatement>(ast::StatementList{});
|
||||
EXPECT_TRUE(b->Is<BlockStatement>());
|
||||
}
|
||||
|
||||
TEST_F(BlockStatementTest, Assert_Null_Statement) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BlockStatement>(ast::StatementList{nullptr});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<BlockStatement>(ast::StatementList{nullptr});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(BlockStatementTest, Assert_DifferentProgramID_Statement) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BlockStatement>(
|
||||
ast::StatementList{b2.create<DiscardStatement>()});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BlockStatement>(ast::StatementList{b2.create<DiscardStatement>()});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -27,12 +27,12 @@ Bool::Bool(Bool&&) = default;
|
||||
Bool::~Bool() = default;
|
||||
|
||||
std::string Bool::FriendlyName(const SymbolTable&) const {
|
||||
return "bool";
|
||||
return "bool";
|
||||
}
|
||||
|
||||
const Bool* Bool::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<Bool>(src);
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<Bool>(src);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -29,24 +29,24 @@ namespace tint::ast {
|
||||
|
||||
/// A boolean type
|
||||
class Bool final : public Castable<Bool, Type> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
Bool(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
Bool(Bool&&);
|
||||
~Bool() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
Bool(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
Bool(Bool&&);
|
||||
~Bool() override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const Bool* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const Bool* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -20,18 +20,15 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::BoolLiteralExpression);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
BoolLiteralExpression::BoolLiteralExpression(ProgramID pid,
|
||||
const Source& src,
|
||||
bool val)
|
||||
BoolLiteralExpression::BoolLiteralExpression(ProgramID pid, const Source& src, bool val)
|
||||
: Base(pid, src), value(val) {}
|
||||
|
||||
BoolLiteralExpression::~BoolLiteralExpression() = default;
|
||||
|
||||
const BoolLiteralExpression* BoolLiteralExpression::Clone(
|
||||
CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<BoolLiteralExpression>(src, value);
|
||||
const BoolLiteralExpression* BoolLiteralExpression::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<BoolLiteralExpression>(src, value);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,24 +22,23 @@
|
||||
namespace tint::ast {
|
||||
|
||||
/// A boolean literal
|
||||
class BoolLiteralExpression final
|
||||
: public Castable<BoolLiteralExpression, LiteralExpression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param value the bool literals value
|
||||
BoolLiteralExpression(ProgramID pid, const Source& src, bool value);
|
||||
~BoolLiteralExpression() override;
|
||||
class BoolLiteralExpression final : public Castable<BoolLiteralExpression, LiteralExpression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param value the bool literals value
|
||||
BoolLiteralExpression(ProgramID pid, const Source& src, bool value);
|
||||
~BoolLiteralExpression() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BoolLiteralExpression* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BoolLiteralExpression* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The boolean literal value
|
||||
const bool value;
|
||||
/// The boolean literal value
|
||||
const bool value;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -20,15 +20,15 @@ namespace {
|
||||
using BoolLiteralExpressionTest = TestHelper;
|
||||
|
||||
TEST_F(BoolLiteralExpressionTest, True) {
|
||||
auto* b = create<BoolLiteralExpression>(true);
|
||||
ASSERT_TRUE(b->Is<BoolLiteralExpression>());
|
||||
ASSERT_TRUE(b->value);
|
||||
auto* b = create<BoolLiteralExpression>(true);
|
||||
ASSERT_TRUE(b->Is<BoolLiteralExpression>());
|
||||
ASSERT_TRUE(b->value);
|
||||
}
|
||||
|
||||
TEST_F(BoolLiteralExpressionTest, False) {
|
||||
auto* b = create<BoolLiteralExpression>(false);
|
||||
ASSERT_TRUE(b->Is<BoolLiteralExpression>());
|
||||
ASSERT_FALSE(b->value);
|
||||
auto* b = create<BoolLiteralExpression>(false);
|
||||
ASSERT_TRUE(b->Is<BoolLiteralExpression>());
|
||||
ASSERT_FALSE(b->value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace {
|
||||
using AstBoolTest = TestHelper;
|
||||
|
||||
TEST_F(AstBoolTest, FriendlyName) {
|
||||
auto* b = create<Bool>();
|
||||
EXPECT_EQ(b->FriendlyName(Symbols()), "bool");
|
||||
auto* b = create<Bool>();
|
||||
EXPECT_EQ(b->FriendlyName(Symbols()), "bool");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -20,17 +20,16 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::BreakStatement);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
BreakStatement::BreakStatement(ProgramID pid, const Source& src)
|
||||
: Base(pid, src) {}
|
||||
BreakStatement::BreakStatement(ProgramID pid, const Source& src) : Base(pid, src) {}
|
||||
|
||||
BreakStatement::BreakStatement(BreakStatement&&) = default;
|
||||
|
||||
BreakStatement::~BreakStatement() = default;
|
||||
|
||||
const BreakStatement* BreakStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<BreakStatement>(src);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<BreakStatement>(src);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -21,20 +21,20 @@ namespace tint::ast {
|
||||
|
||||
/// An break statement
|
||||
class BreakStatement final : public Castable<BreakStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
BreakStatement(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
BreakStatement(BreakStatement&&);
|
||||
~BreakStatement() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
BreakStatement(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
BreakStatement(BreakStatement&&);
|
||||
~BreakStatement() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BreakStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BreakStatement* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,15 +22,15 @@ namespace {
|
||||
using BreakStatementTest = TestHelper;
|
||||
|
||||
TEST_F(BreakStatementTest, Creation_WithSource) {
|
||||
auto* stmt = create<BreakStatement>(Source{Source::Location{20, 2}});
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* stmt = create<BreakStatement>(Source{Source::Location{20, 2}});
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(BreakStatementTest, IsBreak) {
|
||||
auto* stmt = create<BreakStatement>();
|
||||
EXPECT_TRUE(stmt->Is<BreakStatement>());
|
||||
auto* stmt = create<BreakStatement>();
|
||||
EXPECT_TRUE(stmt->Is<BreakStatement>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -17,64 +17,64 @@
|
||||
namespace tint::ast {
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, Builtin builtin) {
|
||||
switch (builtin) {
|
||||
case Builtin::kNone: {
|
||||
out << "none";
|
||||
break;
|
||||
switch (builtin) {
|
||||
case Builtin::kNone: {
|
||||
out << "none";
|
||||
break;
|
||||
}
|
||||
case Builtin::kPosition: {
|
||||
out << "position";
|
||||
break;
|
||||
}
|
||||
case Builtin::kVertexIndex: {
|
||||
out << "vertex_index";
|
||||
break;
|
||||
}
|
||||
case Builtin::kInstanceIndex: {
|
||||
out << "instance_index";
|
||||
break;
|
||||
}
|
||||
case Builtin::kFrontFacing: {
|
||||
out << "front_facing";
|
||||
break;
|
||||
}
|
||||
case Builtin::kFragDepth: {
|
||||
out << "frag_depth";
|
||||
break;
|
||||
}
|
||||
case Builtin::kLocalInvocationId: {
|
||||
out << "local_invocation_id";
|
||||
break;
|
||||
}
|
||||
case Builtin::kLocalInvocationIndex: {
|
||||
out << "local_invocation_index";
|
||||
break;
|
||||
}
|
||||
case Builtin::kGlobalInvocationId: {
|
||||
out << "global_invocation_id";
|
||||
break;
|
||||
}
|
||||
case Builtin::kWorkgroupId: {
|
||||
out << "workgroup_id";
|
||||
break;
|
||||
}
|
||||
case Builtin::kNumWorkgroups: {
|
||||
out << "num_workgroups";
|
||||
break;
|
||||
}
|
||||
case Builtin::kSampleIndex: {
|
||||
out << "sample_index";
|
||||
break;
|
||||
}
|
||||
case Builtin::kSampleMask: {
|
||||
out << "sample_mask";
|
||||
break;
|
||||
}
|
||||
case Builtin::kPointSize: {
|
||||
out << "pointsize";
|
||||
}
|
||||
}
|
||||
case Builtin::kPosition: {
|
||||
out << "position";
|
||||
break;
|
||||
}
|
||||
case Builtin::kVertexIndex: {
|
||||
out << "vertex_index";
|
||||
break;
|
||||
}
|
||||
case Builtin::kInstanceIndex: {
|
||||
out << "instance_index";
|
||||
break;
|
||||
}
|
||||
case Builtin::kFrontFacing: {
|
||||
out << "front_facing";
|
||||
break;
|
||||
}
|
||||
case Builtin::kFragDepth: {
|
||||
out << "frag_depth";
|
||||
break;
|
||||
}
|
||||
case Builtin::kLocalInvocationId: {
|
||||
out << "local_invocation_id";
|
||||
break;
|
||||
}
|
||||
case Builtin::kLocalInvocationIndex: {
|
||||
out << "local_invocation_index";
|
||||
break;
|
||||
}
|
||||
case Builtin::kGlobalInvocationId: {
|
||||
out << "global_invocation_id";
|
||||
break;
|
||||
}
|
||||
case Builtin::kWorkgroupId: {
|
||||
out << "workgroup_id";
|
||||
break;
|
||||
}
|
||||
case Builtin::kNumWorkgroups: {
|
||||
out << "num_workgroups";
|
||||
break;
|
||||
}
|
||||
case Builtin::kSampleIndex: {
|
||||
out << "sample_index";
|
||||
break;
|
||||
}
|
||||
case Builtin::kSampleMask: {
|
||||
out << "sample_mask";
|
||||
break;
|
||||
}
|
||||
case Builtin::kPointSize: {
|
||||
out << "pointsize";
|
||||
}
|
||||
}
|
||||
return out;
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -21,23 +21,23 @@ namespace tint::ast {
|
||||
|
||||
/// The builtin identifiers
|
||||
enum class Builtin {
|
||||
kNone = -1,
|
||||
kPosition,
|
||||
kVertexIndex,
|
||||
kInstanceIndex,
|
||||
kFrontFacing,
|
||||
kFragDepth,
|
||||
kLocalInvocationId,
|
||||
kLocalInvocationIndex,
|
||||
kGlobalInvocationId,
|
||||
kWorkgroupId,
|
||||
kNumWorkgroups,
|
||||
kSampleIndex,
|
||||
kSampleMask,
|
||||
kNone = -1,
|
||||
kPosition,
|
||||
kVertexIndex,
|
||||
kInstanceIndex,
|
||||
kFrontFacing,
|
||||
kFragDepth,
|
||||
kLocalInvocationId,
|
||||
kLocalInvocationIndex,
|
||||
kGlobalInvocationId,
|
||||
kWorkgroupId,
|
||||
kNumWorkgroups,
|
||||
kSampleIndex,
|
||||
kSampleMask,
|
||||
|
||||
// Below are not currently WGSL builtins, but are included in this enum as
|
||||
// they are used by certain backends.
|
||||
kPointSize,
|
||||
// Below are not currently WGSL builtins, but are included in this enum as
|
||||
// they are used by certain backends.
|
||||
kPointSize,
|
||||
};
|
||||
|
||||
/// @param out the std::ostream to write to
|
||||
|
||||
@@ -28,13 +28,13 @@ BuiltinAttribute::BuiltinAttribute(ProgramID pid, const Source& src, Builtin b)
|
||||
BuiltinAttribute::~BuiltinAttribute() = default;
|
||||
|
||||
std::string BuiltinAttribute::Name() const {
|
||||
return "builtin";
|
||||
return "builtin";
|
||||
}
|
||||
|
||||
const BuiltinAttribute* BuiltinAttribute::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<BuiltinAttribute>(src, builtin);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<BuiltinAttribute>(src, builtin);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -24,25 +24,25 @@ namespace tint::ast {
|
||||
|
||||
/// A builtin attribute
|
||||
class BuiltinAttribute final : public Castable<BuiltinAttribute, Attribute> {
|
||||
public:
|
||||
/// constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param builtin the builtin value
|
||||
BuiltinAttribute(ProgramID pid, const Source& src, Builtin builtin);
|
||||
~BuiltinAttribute() override;
|
||||
public:
|
||||
/// constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param builtin the builtin value
|
||||
BuiltinAttribute(ProgramID pid, const Source& src, Builtin builtin);
|
||||
~BuiltinAttribute() override;
|
||||
|
||||
/// @returns the WGSL name for the attribute
|
||||
std::string Name() const override;
|
||||
/// @returns the WGSL name for the attribute
|
||||
std::string Name() const override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BuiltinAttribute* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const BuiltinAttribute* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The builtin value
|
||||
const Builtin builtin;
|
||||
/// The builtin value
|
||||
const Builtin builtin;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace {
|
||||
using BuiltinAttributeTest = TestHelper;
|
||||
|
||||
TEST_F(BuiltinAttributeTest, Creation) {
|
||||
auto* d = create<BuiltinAttribute>(Builtin::kFragDepth);
|
||||
EXPECT_EQ(Builtin::kFragDepth, d->builtin);
|
||||
auto* d = create<BuiltinAttribute>(Builtin::kFragDepth);
|
||||
EXPECT_EQ(Builtin::kFragDepth, d->builtin);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,13 +23,7 @@
|
||||
|
||||
namespace tint::ast::builtin::test {
|
||||
|
||||
enum class TextureKind {
|
||||
kRegular,
|
||||
kDepth,
|
||||
kDepthMultisampled,
|
||||
kMultisampled,
|
||||
kStorage
|
||||
};
|
||||
enum class TextureKind { kRegular, kDepth, kDepthMultisampled, kMultisampled, kStorage };
|
||||
enum class TextureDataType { kF32, kU32, kI32 };
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const TextureKind& kind);
|
||||
@@ -37,144 +31,144 @@ std::ostream& operator<<(std::ostream& out, const TextureDataType& ty);
|
||||
|
||||
/// Non-exhaustive list of valid texture overloads
|
||||
enum class ValidTextureOverload {
|
||||
kDimensions1d,
|
||||
kDimensions2d,
|
||||
kDimensions2dLevel,
|
||||
kDimensions2dArray,
|
||||
kDimensions2dArrayLevel,
|
||||
kDimensions3d,
|
||||
kDimensions3dLevel,
|
||||
kDimensionsCube,
|
||||
kDimensionsCubeLevel,
|
||||
kDimensionsCubeArray,
|
||||
kDimensionsCubeArrayLevel,
|
||||
kDimensionsMultisampled2d,
|
||||
kDimensionsDepth2d,
|
||||
kDimensionsDepth2dLevel,
|
||||
kDimensionsDepth2dArray,
|
||||
kDimensionsDepth2dArrayLevel,
|
||||
kDimensionsDepthCube,
|
||||
kDimensionsDepthCubeLevel,
|
||||
kDimensionsDepthCubeArray,
|
||||
kDimensionsDepthCubeArrayLevel,
|
||||
kDimensionsDepthMultisampled2d,
|
||||
kDimensionsStorageWO1d,
|
||||
kDimensionsStorageWO2d,
|
||||
kDimensionsStorageWO2dArray,
|
||||
kDimensionsStorageWO3d,
|
||||
kGather2dF32,
|
||||
kGather2dOffsetF32,
|
||||
kGather2dArrayF32,
|
||||
kGather2dArrayOffsetF32,
|
||||
kGatherCubeF32,
|
||||
kGatherCubeArrayF32,
|
||||
kGatherDepth2dF32,
|
||||
kGatherDepth2dOffsetF32,
|
||||
kGatherDepth2dArrayF32,
|
||||
kGatherDepth2dArrayOffsetF32,
|
||||
kGatherDepthCubeF32,
|
||||
kGatherDepthCubeArrayF32,
|
||||
kGatherCompareDepth2dF32,
|
||||
kGatherCompareDepth2dOffsetF32,
|
||||
kGatherCompareDepth2dArrayF32,
|
||||
kGatherCompareDepth2dArrayOffsetF32,
|
||||
kGatherCompareDepthCubeF32,
|
||||
kGatherCompareDepthCubeArrayF32,
|
||||
kNumLayers2dArray,
|
||||
kNumLayersCubeArray,
|
||||
kNumLayersDepth2dArray,
|
||||
kNumLayersDepthCubeArray,
|
||||
kNumLayersStorageWO2dArray,
|
||||
kNumLevels2d,
|
||||
kNumLevels2dArray,
|
||||
kNumLevels3d,
|
||||
kNumLevelsCube,
|
||||
kNumLevelsCubeArray,
|
||||
kNumLevelsDepth2d,
|
||||
kNumLevelsDepth2dArray,
|
||||
kNumLevelsDepthCube,
|
||||
kNumLevelsDepthCubeArray,
|
||||
kNumSamplesMultisampled2d,
|
||||
kNumSamplesDepthMultisampled2d,
|
||||
kSample1dF32,
|
||||
kSample2dF32,
|
||||
kSample2dOffsetF32,
|
||||
kSample2dArrayF32,
|
||||
kSample2dArrayOffsetF32,
|
||||
kSample3dF32,
|
||||
kSample3dOffsetF32,
|
||||
kSampleCubeF32,
|
||||
kSampleCubeArrayF32,
|
||||
kSampleDepth2dF32,
|
||||
kSampleDepth2dOffsetF32,
|
||||
kSampleDepth2dArrayF32,
|
||||
kSampleDepth2dArrayOffsetF32,
|
||||
kSampleDepthCubeF32,
|
||||
kSampleDepthCubeArrayF32,
|
||||
kSampleBias2dF32,
|
||||
kSampleBias2dOffsetF32,
|
||||
kSampleBias2dArrayF32,
|
||||
kSampleBias2dArrayOffsetF32,
|
||||
kSampleBias3dF32,
|
||||
kSampleBias3dOffsetF32,
|
||||
kSampleBiasCubeF32,
|
||||
kSampleBiasCubeArrayF32,
|
||||
kSampleLevel2dF32,
|
||||
kSampleLevel2dOffsetF32,
|
||||
kSampleLevel2dArrayF32,
|
||||
kSampleLevel2dArrayOffsetF32,
|
||||
kSampleLevel3dF32,
|
||||
kSampleLevel3dOffsetF32,
|
||||
kSampleLevelCubeF32,
|
||||
kSampleLevelCubeArrayF32,
|
||||
kSampleLevelDepth2dF32,
|
||||
kSampleLevelDepth2dOffsetF32,
|
||||
kSampleLevelDepth2dArrayF32,
|
||||
kSampleLevelDepth2dArrayOffsetF32,
|
||||
kSampleLevelDepthCubeF32,
|
||||
kSampleLevelDepthCubeArrayF32,
|
||||
kSampleGrad2dF32,
|
||||
kSampleGrad2dOffsetF32,
|
||||
kSampleGrad2dArrayF32,
|
||||
kSampleGrad2dArrayOffsetF32,
|
||||
kSampleGrad3dF32,
|
||||
kSampleGrad3dOffsetF32,
|
||||
kSampleGradCubeF32,
|
||||
kSampleGradCubeArrayF32,
|
||||
kSampleCompareDepth2dF32,
|
||||
kSampleCompareDepth2dOffsetF32,
|
||||
kSampleCompareDepth2dArrayF32,
|
||||
kSampleCompareDepth2dArrayOffsetF32,
|
||||
kSampleCompareDepthCubeF32,
|
||||
kSampleCompareDepthCubeArrayF32,
|
||||
kSampleCompareLevelDepth2dF32,
|
||||
kSampleCompareLevelDepth2dOffsetF32,
|
||||
kSampleCompareLevelDepth2dArrayF32,
|
||||
kSampleCompareLevelDepth2dArrayOffsetF32,
|
||||
kSampleCompareLevelDepthCubeF32,
|
||||
kSampleCompareLevelDepthCubeArrayF32,
|
||||
kLoad1dLevelF32,
|
||||
kLoad1dLevelU32,
|
||||
kLoad1dLevelI32,
|
||||
kLoad2dLevelF32,
|
||||
kLoad2dLevelU32,
|
||||
kLoad2dLevelI32,
|
||||
kLoad2dArrayLevelF32,
|
||||
kLoad2dArrayLevelU32,
|
||||
kLoad2dArrayLevelI32,
|
||||
kLoad3dLevelF32,
|
||||
kLoad3dLevelU32,
|
||||
kLoad3dLevelI32,
|
||||
kLoadMultisampled2dF32,
|
||||
kLoadMultisampled2dU32,
|
||||
kLoadMultisampled2dI32,
|
||||
kLoadDepth2dLevelF32,
|
||||
kLoadDepth2dArrayLevelF32,
|
||||
kLoadDepthMultisampled2dF32,
|
||||
kStoreWO1dRgba32float, // Not permutated for all texel formats
|
||||
kStoreWO2dRgba32float, // Not permutated for all texel formats
|
||||
kStoreWO2dArrayRgba32float, // Not permutated for all texel formats
|
||||
kStoreWO3dRgba32float, // Not permutated for all texel formats
|
||||
kDimensions1d,
|
||||
kDimensions2d,
|
||||
kDimensions2dLevel,
|
||||
kDimensions2dArray,
|
||||
kDimensions2dArrayLevel,
|
||||
kDimensions3d,
|
||||
kDimensions3dLevel,
|
||||
kDimensionsCube,
|
||||
kDimensionsCubeLevel,
|
||||
kDimensionsCubeArray,
|
||||
kDimensionsCubeArrayLevel,
|
||||
kDimensionsMultisampled2d,
|
||||
kDimensionsDepth2d,
|
||||
kDimensionsDepth2dLevel,
|
||||
kDimensionsDepth2dArray,
|
||||
kDimensionsDepth2dArrayLevel,
|
||||
kDimensionsDepthCube,
|
||||
kDimensionsDepthCubeLevel,
|
||||
kDimensionsDepthCubeArray,
|
||||
kDimensionsDepthCubeArrayLevel,
|
||||
kDimensionsDepthMultisampled2d,
|
||||
kDimensionsStorageWO1d,
|
||||
kDimensionsStorageWO2d,
|
||||
kDimensionsStorageWO2dArray,
|
||||
kDimensionsStorageWO3d,
|
||||
kGather2dF32,
|
||||
kGather2dOffsetF32,
|
||||
kGather2dArrayF32,
|
||||
kGather2dArrayOffsetF32,
|
||||
kGatherCubeF32,
|
||||
kGatherCubeArrayF32,
|
||||
kGatherDepth2dF32,
|
||||
kGatherDepth2dOffsetF32,
|
||||
kGatherDepth2dArrayF32,
|
||||
kGatherDepth2dArrayOffsetF32,
|
||||
kGatherDepthCubeF32,
|
||||
kGatherDepthCubeArrayF32,
|
||||
kGatherCompareDepth2dF32,
|
||||
kGatherCompareDepth2dOffsetF32,
|
||||
kGatherCompareDepth2dArrayF32,
|
||||
kGatherCompareDepth2dArrayOffsetF32,
|
||||
kGatherCompareDepthCubeF32,
|
||||
kGatherCompareDepthCubeArrayF32,
|
||||
kNumLayers2dArray,
|
||||
kNumLayersCubeArray,
|
||||
kNumLayersDepth2dArray,
|
||||
kNumLayersDepthCubeArray,
|
||||
kNumLayersStorageWO2dArray,
|
||||
kNumLevels2d,
|
||||
kNumLevels2dArray,
|
||||
kNumLevels3d,
|
||||
kNumLevelsCube,
|
||||
kNumLevelsCubeArray,
|
||||
kNumLevelsDepth2d,
|
||||
kNumLevelsDepth2dArray,
|
||||
kNumLevelsDepthCube,
|
||||
kNumLevelsDepthCubeArray,
|
||||
kNumSamplesMultisampled2d,
|
||||
kNumSamplesDepthMultisampled2d,
|
||||
kSample1dF32,
|
||||
kSample2dF32,
|
||||
kSample2dOffsetF32,
|
||||
kSample2dArrayF32,
|
||||
kSample2dArrayOffsetF32,
|
||||
kSample3dF32,
|
||||
kSample3dOffsetF32,
|
||||
kSampleCubeF32,
|
||||
kSampleCubeArrayF32,
|
||||
kSampleDepth2dF32,
|
||||
kSampleDepth2dOffsetF32,
|
||||
kSampleDepth2dArrayF32,
|
||||
kSampleDepth2dArrayOffsetF32,
|
||||
kSampleDepthCubeF32,
|
||||
kSampleDepthCubeArrayF32,
|
||||
kSampleBias2dF32,
|
||||
kSampleBias2dOffsetF32,
|
||||
kSampleBias2dArrayF32,
|
||||
kSampleBias2dArrayOffsetF32,
|
||||
kSampleBias3dF32,
|
||||
kSampleBias3dOffsetF32,
|
||||
kSampleBiasCubeF32,
|
||||
kSampleBiasCubeArrayF32,
|
||||
kSampleLevel2dF32,
|
||||
kSampleLevel2dOffsetF32,
|
||||
kSampleLevel2dArrayF32,
|
||||
kSampleLevel2dArrayOffsetF32,
|
||||
kSampleLevel3dF32,
|
||||
kSampleLevel3dOffsetF32,
|
||||
kSampleLevelCubeF32,
|
||||
kSampleLevelCubeArrayF32,
|
||||
kSampleLevelDepth2dF32,
|
||||
kSampleLevelDepth2dOffsetF32,
|
||||
kSampleLevelDepth2dArrayF32,
|
||||
kSampleLevelDepth2dArrayOffsetF32,
|
||||
kSampleLevelDepthCubeF32,
|
||||
kSampleLevelDepthCubeArrayF32,
|
||||
kSampleGrad2dF32,
|
||||
kSampleGrad2dOffsetF32,
|
||||
kSampleGrad2dArrayF32,
|
||||
kSampleGrad2dArrayOffsetF32,
|
||||
kSampleGrad3dF32,
|
||||
kSampleGrad3dOffsetF32,
|
||||
kSampleGradCubeF32,
|
||||
kSampleGradCubeArrayF32,
|
||||
kSampleCompareDepth2dF32,
|
||||
kSampleCompareDepth2dOffsetF32,
|
||||
kSampleCompareDepth2dArrayF32,
|
||||
kSampleCompareDepth2dArrayOffsetF32,
|
||||
kSampleCompareDepthCubeF32,
|
||||
kSampleCompareDepthCubeArrayF32,
|
||||
kSampleCompareLevelDepth2dF32,
|
||||
kSampleCompareLevelDepth2dOffsetF32,
|
||||
kSampleCompareLevelDepth2dArrayF32,
|
||||
kSampleCompareLevelDepth2dArrayOffsetF32,
|
||||
kSampleCompareLevelDepthCubeF32,
|
||||
kSampleCompareLevelDepthCubeArrayF32,
|
||||
kLoad1dLevelF32,
|
||||
kLoad1dLevelU32,
|
||||
kLoad1dLevelI32,
|
||||
kLoad2dLevelF32,
|
||||
kLoad2dLevelU32,
|
||||
kLoad2dLevelI32,
|
||||
kLoad2dArrayLevelF32,
|
||||
kLoad2dArrayLevelU32,
|
||||
kLoad2dArrayLevelI32,
|
||||
kLoad3dLevelF32,
|
||||
kLoad3dLevelU32,
|
||||
kLoad3dLevelI32,
|
||||
kLoadMultisampled2dF32,
|
||||
kLoadMultisampled2dU32,
|
||||
kLoadMultisampled2dI32,
|
||||
kLoadDepth2dLevelF32,
|
||||
kLoadDepth2dArrayLevelF32,
|
||||
kLoadDepthMultisampled2dF32,
|
||||
kStoreWO1dRgba32float, // Not permutated for all texel formats
|
||||
kStoreWO2dRgba32float, // Not permutated for all texel formats
|
||||
kStoreWO2dArrayRgba32float, // Not permutated for all texel formats
|
||||
kStoreWO3dRgba32float, // Not permutated for all texel formats
|
||||
};
|
||||
|
||||
/// @param texture_overload the ValidTextureOverload
|
||||
@@ -183,77 +177,76 @@ bool ReturnsVoid(ValidTextureOverload texture_overload);
|
||||
|
||||
/// Describes a texture builtin overload
|
||||
struct TextureOverloadCase {
|
||||
/// Constructor for textureSample...() functions
|
||||
TextureOverloadCase(ValidTextureOverload,
|
||||
const char*,
|
||||
TextureKind,
|
||||
ast::SamplerKind,
|
||||
ast::TextureDimension,
|
||||
TextureDataType,
|
||||
const char*,
|
||||
std::function<ExpressionList(ProgramBuilder*)>);
|
||||
/// Constructor for textureLoad() functions with non-storage textures
|
||||
TextureOverloadCase(ValidTextureOverload,
|
||||
const char*,
|
||||
TextureKind,
|
||||
ast::TextureDimension,
|
||||
TextureDataType,
|
||||
const char*,
|
||||
std::function<ExpressionList(ProgramBuilder*)>);
|
||||
/// Constructor for textureLoad() with storage textures
|
||||
TextureOverloadCase(ValidTextureOverload,
|
||||
const char*,
|
||||
Access,
|
||||
ast::TexelFormat,
|
||||
ast::TextureDimension,
|
||||
TextureDataType,
|
||||
const char*,
|
||||
std::function<ExpressionList(ProgramBuilder*)>);
|
||||
/// Copy constructor
|
||||
TextureOverloadCase(const TextureOverloadCase&);
|
||||
/// Destructor
|
||||
~TextureOverloadCase();
|
||||
/// Constructor for textureSample...() functions
|
||||
TextureOverloadCase(ValidTextureOverload,
|
||||
const char*,
|
||||
TextureKind,
|
||||
ast::SamplerKind,
|
||||
ast::TextureDimension,
|
||||
TextureDataType,
|
||||
const char*,
|
||||
std::function<ExpressionList(ProgramBuilder*)>);
|
||||
/// Constructor for textureLoad() functions with non-storage textures
|
||||
TextureOverloadCase(ValidTextureOverload,
|
||||
const char*,
|
||||
TextureKind,
|
||||
ast::TextureDimension,
|
||||
TextureDataType,
|
||||
const char*,
|
||||
std::function<ExpressionList(ProgramBuilder*)>);
|
||||
/// Constructor for textureLoad() with storage textures
|
||||
TextureOverloadCase(ValidTextureOverload,
|
||||
const char*,
|
||||
Access,
|
||||
ast::TexelFormat,
|
||||
ast::TextureDimension,
|
||||
TextureDataType,
|
||||
const char*,
|
||||
std::function<ExpressionList(ProgramBuilder*)>);
|
||||
/// Copy constructor
|
||||
TextureOverloadCase(const TextureOverloadCase&);
|
||||
/// Destructor
|
||||
~TextureOverloadCase();
|
||||
|
||||
/// @return a vector containing a large number (non-exhaustive) of valid
|
||||
/// texture overloads.
|
||||
static std::vector<TextureOverloadCase> ValidCases();
|
||||
/// @return a vector containing a large number (non-exhaustive) of valid
|
||||
/// texture overloads.
|
||||
static std::vector<TextureOverloadCase> ValidCases();
|
||||
|
||||
/// @param builder the AST builder used for the test
|
||||
/// @returns the vector component type of the texture function return value
|
||||
const ast::Type* BuildResultVectorComponentType(
|
||||
ProgramBuilder* builder) const;
|
||||
/// @param builder the AST builder used for the test
|
||||
/// @returns a variable holding the test texture, automatically registered as
|
||||
/// a global variable.
|
||||
const ast::Variable* BuildTextureVariable(ProgramBuilder* builder) const;
|
||||
/// @param builder the AST builder used for the test
|
||||
/// @returns a Variable holding the test sampler, automatically registered as
|
||||
/// a global variable.
|
||||
const ast::Variable* BuildSamplerVariable(ProgramBuilder* builder) const;
|
||||
/// @param builder the AST builder used for the test
|
||||
/// @returns the vector component type of the texture function return value
|
||||
const ast::Type* BuildResultVectorComponentType(ProgramBuilder* builder) const;
|
||||
/// @param builder the AST builder used for the test
|
||||
/// @returns a variable holding the test texture, automatically registered as
|
||||
/// a global variable.
|
||||
const ast::Variable* BuildTextureVariable(ProgramBuilder* builder) const;
|
||||
/// @param builder the AST builder used for the test
|
||||
/// @returns a Variable holding the test sampler, automatically registered as
|
||||
/// a global variable.
|
||||
const ast::Variable* BuildSamplerVariable(ProgramBuilder* builder) const;
|
||||
|
||||
/// The enumerator for this overload
|
||||
const ValidTextureOverload overload;
|
||||
/// A human readable description of the overload
|
||||
const char* const description;
|
||||
/// The texture kind for the texture parameter
|
||||
const TextureKind texture_kind;
|
||||
/// The sampler kind for the sampler parameter
|
||||
/// Used only when texture_kind is not kStorage
|
||||
ast::SamplerKind const sampler_kind = ast::SamplerKind::kSampler;
|
||||
/// The access control for the storage texture
|
||||
/// Used only when texture_kind is kStorage
|
||||
Access const access = Access::kReadWrite;
|
||||
/// The image format for the storage texture
|
||||
/// Used only when texture_kind is kStorage
|
||||
ast::TexelFormat const texel_format = ast::TexelFormat::kNone;
|
||||
/// The dimensions of the texture parameter
|
||||
ast::TextureDimension const texture_dimension;
|
||||
/// The data type of the texture parameter
|
||||
const TextureDataType texture_data_type;
|
||||
/// Name of the function. e.g. `textureSample`, `textureSampleGrad`, etc
|
||||
const char* const function;
|
||||
/// A function that builds the AST arguments for the overload
|
||||
std::function<ExpressionList(ProgramBuilder*)> const args;
|
||||
/// The enumerator for this overload
|
||||
const ValidTextureOverload overload;
|
||||
/// A human readable description of the overload
|
||||
const char* const description;
|
||||
/// The texture kind for the texture parameter
|
||||
const TextureKind texture_kind;
|
||||
/// The sampler kind for the sampler parameter
|
||||
/// Used only when texture_kind is not kStorage
|
||||
ast::SamplerKind const sampler_kind = ast::SamplerKind::kSampler;
|
||||
/// The access control for the storage texture
|
||||
/// Used only when texture_kind is kStorage
|
||||
Access const access = Access::kReadWrite;
|
||||
/// The image format for the storage texture
|
||||
/// Used only when texture_kind is kStorage
|
||||
ast::TexelFormat const texel_format = ast::TexelFormat::kNone;
|
||||
/// The dimensions of the texture parameter
|
||||
ast::TextureDimension const texture_dimension;
|
||||
/// The data type of the texture parameter
|
||||
const TextureDataType texture_data_type;
|
||||
/// Name of the function. e.g. `textureSample`, `textureSampleGrad`, etc
|
||||
const char* const function;
|
||||
/// A function that builds the AST arguments for the overload
|
||||
std::function<ExpressionList(ProgramBuilder*)> const args;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data);
|
||||
|
||||
@@ -22,14 +22,14 @@ namespace tint::ast {
|
||||
|
||||
namespace {
|
||||
CallExpression::Target ToTarget(const IdentifierExpression* name) {
|
||||
CallExpression::Target target;
|
||||
target.name = name;
|
||||
return target;
|
||||
CallExpression::Target target;
|
||||
target.name = name;
|
||||
return target;
|
||||
}
|
||||
CallExpression::Target ToTarget(const Type* type) {
|
||||
CallExpression::Target target;
|
||||
target.type = type;
|
||||
return target;
|
||||
CallExpression::Target target;
|
||||
target.type = type;
|
||||
return target;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -38,25 +38,22 @@ CallExpression::CallExpression(ProgramID pid,
|
||||
const IdentifierExpression* name,
|
||||
ExpressionList a)
|
||||
: Base(pid, src), target(ToTarget(name)), args(a) {
|
||||
TINT_ASSERT(AST, name);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, name, program_id);
|
||||
for (auto* arg : args) {
|
||||
TINT_ASSERT(AST, arg);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, arg, program_id);
|
||||
}
|
||||
TINT_ASSERT(AST, name);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, name, program_id);
|
||||
for (auto* arg : args) {
|
||||
TINT_ASSERT(AST, arg);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, arg, program_id);
|
||||
}
|
||||
}
|
||||
|
||||
CallExpression::CallExpression(ProgramID pid,
|
||||
const Source& src,
|
||||
const Type* type,
|
||||
ExpressionList a)
|
||||
CallExpression::CallExpression(ProgramID pid, const Source& src, const Type* type, ExpressionList a)
|
||||
: Base(pid, src), target(ToTarget(type)), args(a) {
|
||||
TINT_ASSERT(AST, type);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
|
||||
for (auto* arg : args) {
|
||||
TINT_ASSERT(AST, arg);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, arg, program_id);
|
||||
}
|
||||
TINT_ASSERT(AST, type);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
|
||||
for (auto* arg : args) {
|
||||
TINT_ASSERT(AST, arg);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, arg, program_id);
|
||||
}
|
||||
}
|
||||
|
||||
CallExpression::CallExpression(CallExpression&&) = default;
|
||||
@@ -64,13 +61,11 @@ CallExpression::CallExpression(CallExpression&&) = default;
|
||||
CallExpression::~CallExpression() = default;
|
||||
|
||||
const CallExpression* CallExpression::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto p = ctx->Clone(args);
|
||||
return target.name
|
||||
? ctx->dst->create<CallExpression>(src, ctx->Clone(target.name), p)
|
||||
: ctx->dst->create<CallExpression>(src, ctx->Clone(target.type),
|
||||
p);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto p = ctx->Clone(args);
|
||||
return target.name ? ctx->dst->create<CallExpression>(src, ctx->Clone(target.name), p)
|
||||
: ctx->dst->create<CallExpression>(src, ctx->Clone(target.type), p);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -31,52 +31,52 @@ namespace tint::ast {
|
||||
/// * sem::TypeConstructor
|
||||
/// * sem::TypeConversion
|
||||
class CallExpression final : public Castable<CallExpression, Expression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the call expression source
|
||||
/// @param name the function or type name
|
||||
/// @param args the arguments
|
||||
CallExpression(ProgramID program_id,
|
||||
const Source& source,
|
||||
const IdentifierExpression* name,
|
||||
ExpressionList args);
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the call expression source
|
||||
/// @param name the function or type name
|
||||
/// @param args the arguments
|
||||
CallExpression(ProgramID program_id,
|
||||
const Source& source,
|
||||
const IdentifierExpression* name,
|
||||
ExpressionList args);
|
||||
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the call expression source
|
||||
/// @param type the type
|
||||
/// @param args the arguments
|
||||
CallExpression(ProgramID program_id,
|
||||
const Source& source,
|
||||
const Type* type,
|
||||
ExpressionList args);
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the call expression source
|
||||
/// @param type the type
|
||||
/// @param args the arguments
|
||||
CallExpression(ProgramID program_id,
|
||||
const Source& source,
|
||||
const Type* type,
|
||||
ExpressionList args);
|
||||
|
||||
/// Move constructor
|
||||
CallExpression(CallExpression&&);
|
||||
~CallExpression() override;
|
||||
/// Move constructor
|
||||
CallExpression(CallExpression&&);
|
||||
~CallExpression() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CallExpression* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CallExpression* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// Target is either an identifier, or a Type.
|
||||
/// One of these must be nullptr and the other a non-nullptr.
|
||||
struct Target {
|
||||
/// name is a function or builtin to call, or type name to construct or
|
||||
/// cast-to
|
||||
const IdentifierExpression* name = nullptr;
|
||||
/// type to construct or cast-to
|
||||
const Type* type = nullptr;
|
||||
};
|
||||
/// Target is either an identifier, or a Type.
|
||||
/// One of these must be nullptr and the other a non-nullptr.
|
||||
struct Target {
|
||||
/// name is a function or builtin to call, or type name to construct or
|
||||
/// cast-to
|
||||
const IdentifierExpression* name = nullptr;
|
||||
/// type to construct or cast-to
|
||||
const Type* type = nullptr;
|
||||
};
|
||||
|
||||
/// The target function
|
||||
const Target target;
|
||||
/// The target function
|
||||
const Target target;
|
||||
|
||||
/// The arguments
|
||||
const ExpressionList args;
|
||||
/// The arguments
|
||||
const ExpressionList args;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -21,126 +21,124 @@ namespace {
|
||||
using CallExpressionTest = TestHelper;
|
||||
|
||||
TEST_F(CallExpressionTest, CreationIdentifier) {
|
||||
auto* func = Expr("func");
|
||||
ExpressionList params;
|
||||
params.push_back(Expr("param1"));
|
||||
params.push_back(Expr("param2"));
|
||||
auto* func = Expr("func");
|
||||
ExpressionList params;
|
||||
params.push_back(Expr("param1"));
|
||||
params.push_back(Expr("param2"));
|
||||
|
||||
auto* stmt = create<CallExpression>(func, params);
|
||||
EXPECT_EQ(stmt->target.name, func);
|
||||
EXPECT_EQ(stmt->target.type, nullptr);
|
||||
auto* stmt = create<CallExpression>(func, params);
|
||||
EXPECT_EQ(stmt->target.name, func);
|
||||
EXPECT_EQ(stmt->target.type, nullptr);
|
||||
|
||||
const auto& vec = stmt->args;
|
||||
ASSERT_EQ(vec.size(), 2u);
|
||||
EXPECT_EQ(vec[0], params[0]);
|
||||
EXPECT_EQ(vec[1], params[1]);
|
||||
const auto& vec = stmt->args;
|
||||
ASSERT_EQ(vec.size(), 2u);
|
||||
EXPECT_EQ(vec[0], params[0]);
|
||||
EXPECT_EQ(vec[1], params[1]);
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, CreationIdentifier_WithSource) {
|
||||
auto* func = Expr("func");
|
||||
auto* stmt = create<CallExpression>(Source{{20, 2}}, func, ExpressionList{});
|
||||
EXPECT_EQ(stmt->target.name, func);
|
||||
EXPECT_EQ(stmt->target.type, nullptr);
|
||||
auto* func = Expr("func");
|
||||
auto* stmt = create<CallExpression>(Source{{20, 2}}, func, ExpressionList{});
|
||||
EXPECT_EQ(stmt->target.name, func);
|
||||
EXPECT_EQ(stmt->target.type, nullptr);
|
||||
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, CreationType) {
|
||||
auto* type = ty.f32();
|
||||
ExpressionList params;
|
||||
params.push_back(Expr("param1"));
|
||||
params.push_back(Expr("param2"));
|
||||
auto* type = ty.f32();
|
||||
ExpressionList params;
|
||||
params.push_back(Expr("param1"));
|
||||
params.push_back(Expr("param2"));
|
||||
|
||||
auto* stmt = create<CallExpression>(type, params);
|
||||
EXPECT_EQ(stmt->target.name, nullptr);
|
||||
EXPECT_EQ(stmt->target.type, type);
|
||||
auto* stmt = create<CallExpression>(type, params);
|
||||
EXPECT_EQ(stmt->target.name, nullptr);
|
||||
EXPECT_EQ(stmt->target.type, type);
|
||||
|
||||
const auto& vec = stmt->args;
|
||||
ASSERT_EQ(vec.size(), 2u);
|
||||
EXPECT_EQ(vec[0], params[0]);
|
||||
EXPECT_EQ(vec[1], params[1]);
|
||||
const auto& vec = stmt->args;
|
||||
ASSERT_EQ(vec.size(), 2u);
|
||||
EXPECT_EQ(vec[0], params[0]);
|
||||
EXPECT_EQ(vec[1], params[1]);
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, CreationType_WithSource) {
|
||||
auto* type = ty.f32();
|
||||
auto* stmt = create<CallExpression>(Source{{20, 2}}, type, ExpressionList{});
|
||||
EXPECT_EQ(stmt->target.name, nullptr);
|
||||
EXPECT_EQ(stmt->target.type, type);
|
||||
auto* type = ty.f32();
|
||||
auto* stmt = create<CallExpression>(Source{{20, 2}}, type, ExpressionList{});
|
||||
EXPECT_EQ(stmt->target.name, nullptr);
|
||||
EXPECT_EQ(stmt->target.type, type);
|
||||
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, IsCall) {
|
||||
auto* func = Expr("func");
|
||||
auto* stmt = create<CallExpression>(func, ExpressionList{});
|
||||
EXPECT_TRUE(stmt->Is<CallExpression>());
|
||||
auto* func = Expr("func");
|
||||
auto* stmt = create<CallExpression>(func, ExpressionList{});
|
||||
EXPECT_TRUE(stmt->Is<CallExpression>());
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, Assert_Null_Identifier) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CallExpression>(static_cast<IdentifierExpression*>(nullptr),
|
||||
ExpressionList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CallExpression>(static_cast<IdentifierExpression*>(nullptr), ExpressionList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, Assert_Null_Type) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CallExpression>(static_cast<Type*>(nullptr), ExpressionList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CallExpression>(static_cast<Type*>(nullptr), ExpressionList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, Assert_Null_Param) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
ExpressionList params;
|
||||
params.push_back(b.Expr("param1"));
|
||||
params.push_back(nullptr);
|
||||
params.push_back(b.Expr("param2"));
|
||||
b.create<CallExpression>(b.Expr("func"), params);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
ExpressionList params;
|
||||
params.push_back(b.Expr("param1"));
|
||||
params.push_back(nullptr);
|
||||
params.push_back(b.Expr("param2"));
|
||||
b.create<CallExpression>(b.Expr("func"), params);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, Assert_DifferentProgramID_Identifier) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CallExpression>(b2.Expr("func"), ExpressionList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CallExpression>(b2.Expr("func"), ExpressionList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, Assert_DifferentProgramID_Type) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CallExpression>(b2.ty.f32(), ExpressionList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CallExpression>(b2.ty.f32(), ExpressionList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CallExpressionTest, Assert_DifferentProgramID_Param) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CallExpression>(b1.Expr("func"),
|
||||
ExpressionList{b2.Expr("param1")});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CallExpression>(b1.Expr("func"), ExpressionList{b2.Expr("param1")});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -20,12 +20,10 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::CallStatement);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
CallStatement::CallStatement(ProgramID pid,
|
||||
const Source& src,
|
||||
const CallExpression* call)
|
||||
CallStatement::CallStatement(ProgramID pid, const Source& src, const CallExpression* call)
|
||||
: Base(pid, src), expr(call) {
|
||||
TINT_ASSERT(AST, expr);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr, program_id);
|
||||
TINT_ASSERT(AST, expr);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr, program_id);
|
||||
}
|
||||
|
||||
CallStatement::CallStatement(CallStatement&&) = default;
|
||||
@@ -33,10 +31,10 @@ CallStatement::CallStatement(CallStatement&&) = default;
|
||||
CallStatement::~CallStatement() = default;
|
||||
|
||||
const CallStatement* CallStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* call = ctx->Clone(expr);
|
||||
return ctx->dst->create<CallStatement>(src, call);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* call = ctx->Clone(expr);
|
||||
return ctx->dst->create<CallStatement>(src, call);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,24 +22,24 @@ namespace tint::ast {
|
||||
|
||||
/// A call expression
|
||||
class CallStatement final : public Castable<CallStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node for the statement
|
||||
/// @param call the function
|
||||
CallStatement(ProgramID pid, const Source& src, const CallExpression* call);
|
||||
/// Move constructor
|
||||
CallStatement(CallStatement&&);
|
||||
~CallStatement() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node for the statement
|
||||
/// @param call the function
|
||||
CallStatement(ProgramID pid, const Source& src, const CallExpression* call);
|
||||
/// Move constructor
|
||||
CallStatement(CallStatement&&);
|
||||
~CallStatement() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CallStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CallStatement* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The call expression
|
||||
const CallExpression* const expr;
|
||||
/// The call expression
|
||||
const CallExpression* const expr;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,35 +23,34 @@ namespace {
|
||||
using CallStatementTest = TestHelper;
|
||||
|
||||
TEST_F(CallStatementTest, Creation) {
|
||||
auto* expr = create<CallExpression>(Expr("func"), ExpressionList{});
|
||||
auto* expr = create<CallExpression>(Expr("func"), ExpressionList{});
|
||||
|
||||
auto* c = create<CallStatement>(expr);
|
||||
EXPECT_EQ(c->expr, expr);
|
||||
auto* c = create<CallStatement>(expr);
|
||||
EXPECT_EQ(c->expr, expr);
|
||||
}
|
||||
|
||||
TEST_F(CallStatementTest, IsCall) {
|
||||
auto* c = create<CallStatement>(Call("f"));
|
||||
EXPECT_TRUE(c->Is<CallStatement>());
|
||||
auto* c = create<CallStatement>(Call("f"));
|
||||
EXPECT_TRUE(c->Is<CallStatement>());
|
||||
}
|
||||
|
||||
TEST_F(CallStatementTest, Assert_Null_Call) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CallStatement>(nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CallStatement>(nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CallStatementTest, Assert_DifferentProgramID_Call) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CallStatement>(
|
||||
b2.create<CallExpression>(b2.Expr("func"), ExpressionList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CallStatement>(b2.create<CallExpression>(b2.Expr("func"), ExpressionList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -25,12 +25,12 @@ CaseStatement::CaseStatement(ProgramID pid,
|
||||
CaseSelectorList s,
|
||||
const BlockStatement* b)
|
||||
: Base(pid, src), selectors(s), body(b) {
|
||||
TINT_ASSERT(AST, body);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
||||
for (auto* selector : selectors) {
|
||||
TINT_ASSERT(AST, selector);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, selector, program_id);
|
||||
}
|
||||
TINT_ASSERT(AST, body);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
||||
for (auto* selector : selectors) {
|
||||
TINT_ASSERT(AST, selector);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, selector, program_id);
|
||||
}
|
||||
}
|
||||
|
||||
CaseStatement::CaseStatement(CaseStatement&&) = default;
|
||||
@@ -38,11 +38,11 @@ CaseStatement::CaseStatement(CaseStatement&&) = default;
|
||||
CaseStatement::~CaseStatement() = default;
|
||||
|
||||
const CaseStatement* CaseStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto sel = ctx->Clone(selectors);
|
||||
auto* b = ctx->Clone(body);
|
||||
return ctx->dst->create<CaseStatement>(src, sel, b);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto sel = ctx->Clone(selectors);
|
||||
auto* b = ctx->Clone(body);
|
||||
return ctx->dst->create<CaseStatement>(src, sel, b);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -27,34 +27,34 @@ using CaseSelectorList = std::vector<const IntLiteralExpression*>;
|
||||
|
||||
/// A case statement
|
||||
class CaseStatement final : public Castable<CaseStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param selectors the case selectors
|
||||
/// @param body the case body
|
||||
CaseStatement(ProgramID pid,
|
||||
const Source& src,
|
||||
CaseSelectorList selectors,
|
||||
const BlockStatement* body);
|
||||
/// Move constructor
|
||||
CaseStatement(CaseStatement&&);
|
||||
~CaseStatement() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param selectors the case selectors
|
||||
/// @param body the case body
|
||||
CaseStatement(ProgramID pid,
|
||||
const Source& src,
|
||||
CaseSelectorList selectors,
|
||||
const BlockStatement* body);
|
||||
/// Move constructor
|
||||
CaseStatement(CaseStatement&&);
|
||||
~CaseStatement() override;
|
||||
|
||||
/// @returns true if this is a default statement
|
||||
bool IsDefault() const { return selectors.empty(); }
|
||||
/// @returns true if this is a default statement
|
||||
bool IsDefault() const { return selectors.empty(); }
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CaseStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CaseStatement* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The case selectors, empty if none set
|
||||
const CaseSelectorList selectors;
|
||||
/// The case selectors, empty if none set
|
||||
const CaseSelectorList selectors;
|
||||
|
||||
/// The case body
|
||||
const BlockStatement* const body;
|
||||
/// The case body
|
||||
const BlockStatement* const body;
|
||||
};
|
||||
|
||||
/// A list of case statements
|
||||
|
||||
@@ -25,110 +25,108 @@ namespace {
|
||||
using CaseStatementTest = TestHelper;
|
||||
|
||||
TEST_F(CaseStatementTest, Creation_i32) {
|
||||
CaseSelectorList b;
|
||||
auto* selector = create<SintLiteralExpression>(2);
|
||||
b.push_back(selector);
|
||||
CaseSelectorList b;
|
||||
auto* selector = create<SintLiteralExpression>(2);
|
||||
b.push_back(selector);
|
||||
|
||||
auto* discard = create<DiscardStatement>();
|
||||
auto* body = create<BlockStatement>(StatementList{discard});
|
||||
auto* discard = create<DiscardStatement>();
|
||||
auto* body = create<BlockStatement>(StatementList{discard});
|
||||
|
||||
auto* c = create<CaseStatement>(b, body);
|
||||
ASSERT_EQ(c->selectors.size(), 1u);
|
||||
EXPECT_EQ(c->selectors[0], selector);
|
||||
ASSERT_EQ(c->body->statements.size(), 1u);
|
||||
EXPECT_EQ(c->body->statements[0], discard);
|
||||
auto* c = create<CaseStatement>(b, body);
|
||||
ASSERT_EQ(c->selectors.size(), 1u);
|
||||
EXPECT_EQ(c->selectors[0], selector);
|
||||
ASSERT_EQ(c->body->statements.size(), 1u);
|
||||
EXPECT_EQ(c->body->statements[0], discard);
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Creation_u32) {
|
||||
CaseSelectorList b;
|
||||
auto* selector = create<UintLiteralExpression>(2u);
|
||||
b.push_back(selector);
|
||||
CaseSelectorList b;
|
||||
auto* selector = create<UintLiteralExpression>(2u);
|
||||
b.push_back(selector);
|
||||
|
||||
auto* discard = create<DiscardStatement>();
|
||||
auto* body = create<BlockStatement>(StatementList{discard});
|
||||
auto* discard = create<DiscardStatement>();
|
||||
auto* body = create<BlockStatement>(StatementList{discard});
|
||||
|
||||
auto* c = create<CaseStatement>(b, body);
|
||||
ASSERT_EQ(c->selectors.size(), 1u);
|
||||
EXPECT_EQ(c->selectors[0], selector);
|
||||
ASSERT_EQ(c->body->statements.size(), 1u);
|
||||
EXPECT_EQ(c->body->statements[0], discard);
|
||||
auto* c = create<CaseStatement>(b, body);
|
||||
ASSERT_EQ(c->selectors.size(), 1u);
|
||||
EXPECT_EQ(c->selectors[0], selector);
|
||||
ASSERT_EQ(c->body->statements.size(), 1u);
|
||||
EXPECT_EQ(c->body->statements[0], discard);
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<SintLiteralExpression>(2));
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<SintLiteralExpression>(2));
|
||||
|
||||
auto* body = create<BlockStatement>(StatementList{
|
||||
create<DiscardStatement>(),
|
||||
});
|
||||
auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
|
||||
auto src = c->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* body = create<BlockStatement>(StatementList{
|
||||
create<DiscardStatement>(),
|
||||
});
|
||||
auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
|
||||
auto src = c->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, IsDefault_WithoutSelectors) {
|
||||
auto* body = create<BlockStatement>(StatementList{
|
||||
create<DiscardStatement>(),
|
||||
});
|
||||
auto* c = create<CaseStatement>(CaseSelectorList{}, body);
|
||||
EXPECT_TRUE(c->IsDefault());
|
||||
auto* body = create<BlockStatement>(StatementList{
|
||||
create<DiscardStatement>(),
|
||||
});
|
||||
auto* c = create<CaseStatement>(CaseSelectorList{}, body);
|
||||
EXPECT_TRUE(c->IsDefault());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, IsDefault_WithSelectors) {
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<SintLiteralExpression>(2));
|
||||
CaseSelectorList b;
|
||||
b.push_back(create<SintLiteralExpression>(2));
|
||||
|
||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(StatementList{}));
|
||||
EXPECT_FALSE(c->IsDefault());
|
||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(StatementList{}));
|
||||
EXPECT_FALSE(c->IsDefault());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, IsCase) {
|
||||
auto* c = create<CaseStatement>(CaseSelectorList{},
|
||||
create<BlockStatement>(StatementList{}));
|
||||
EXPECT_TRUE(c->Is<CaseStatement>());
|
||||
auto* c = create<CaseStatement>(CaseSelectorList{}, create<BlockStatement>(StatementList{}));
|
||||
EXPECT_TRUE(c->Is<CaseStatement>());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Assert_Null_Body) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CaseStatement>(CaseSelectorList{}, nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CaseStatement>(CaseSelectorList{}, nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Assert_Null_Selector) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CaseStatement>(CaseSelectorList{nullptr},
|
||||
b.create<BlockStatement>(StatementList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CaseStatement>(CaseSelectorList{nullptr},
|
||||
b.create<BlockStatement>(StatementList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Assert_DifferentProgramID_Call) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CaseStatement>(CaseSelectorList{},
|
||||
b2.create<BlockStatement>(StatementList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CaseStatement>(CaseSelectorList{},
|
||||
b2.create<BlockStatement>(StatementList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Assert_DifferentProgramID_Selector) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CaseStatement>(
|
||||
CaseSelectorList{b2.create<SintLiteralExpression>(2)},
|
||||
b1.create<BlockStatement>(StatementList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CaseStatement>(CaseSelectorList{b2.create<SintLiteralExpression>(2)},
|
||||
b1.create<BlockStatement>(StatementList{}));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -26,24 +26,22 @@ CompoundAssignmentStatement::CompoundAssignmentStatement(ProgramID pid,
|
||||
const Expression* r,
|
||||
BinaryOp o)
|
||||
: Base(pid, src), lhs(l), rhs(r), op(o) {
|
||||
TINT_ASSERT(AST, lhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
|
||||
TINT_ASSERT(AST, rhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id);
|
||||
TINT_ASSERT(AST, lhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
|
||||
TINT_ASSERT(AST, rhs);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id);
|
||||
}
|
||||
|
||||
CompoundAssignmentStatement::CompoundAssignmentStatement(
|
||||
CompoundAssignmentStatement&&) = default;
|
||||
CompoundAssignmentStatement::CompoundAssignmentStatement(CompoundAssignmentStatement&&) = default;
|
||||
|
||||
CompoundAssignmentStatement::~CompoundAssignmentStatement() = default;
|
||||
|
||||
const CompoundAssignmentStatement* CompoundAssignmentStatement::Clone(
|
||||
CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* l = ctx->Clone(lhs);
|
||||
auto* r = ctx->Clone(rhs);
|
||||
return ctx->dst->create<CompoundAssignmentStatement>(src, l, r, op);
|
||||
const CompoundAssignmentStatement* CompoundAssignmentStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto* l = ctx->Clone(lhs);
|
||||
auto* r = ctx->Clone(rhs);
|
||||
return ctx->dst->create<CompoundAssignmentStatement>(src, l, r, op);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,38 +22,37 @@
|
||||
namespace tint::ast {
|
||||
|
||||
/// A compound assignment statement
|
||||
class CompoundAssignmentStatement final
|
||||
: public Castable<CompoundAssignmentStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the compound assignment statement source
|
||||
/// @param lhs the left side of the expression
|
||||
/// @param rhs the right side of the expression
|
||||
/// @param op the binary operator
|
||||
CompoundAssignmentStatement(ProgramID program_id,
|
||||
const Source& source,
|
||||
const Expression* lhs,
|
||||
const Expression* rhs,
|
||||
BinaryOp op);
|
||||
/// Move constructor
|
||||
CompoundAssignmentStatement(CompoundAssignmentStatement&&);
|
||||
~CompoundAssignmentStatement() override;
|
||||
class CompoundAssignmentStatement final : public Castable<CompoundAssignmentStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the compound assignment statement source
|
||||
/// @param lhs the left side of the expression
|
||||
/// @param rhs the right side of the expression
|
||||
/// @param op the binary operator
|
||||
CompoundAssignmentStatement(ProgramID program_id,
|
||||
const Source& source,
|
||||
const Expression* lhs,
|
||||
const Expression* rhs,
|
||||
BinaryOp op);
|
||||
/// Move constructor
|
||||
CompoundAssignmentStatement(CompoundAssignmentStatement&&);
|
||||
~CompoundAssignmentStatement() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CompoundAssignmentStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const CompoundAssignmentStatement* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// left side expression
|
||||
const Expression* const lhs;
|
||||
/// left side expression
|
||||
const Expression* const lhs;
|
||||
|
||||
/// right side expression
|
||||
const Expression* const rhs;
|
||||
/// right side expression
|
||||
const Expression* const rhs;
|
||||
|
||||
/// the binary operator
|
||||
const BinaryOp op;
|
||||
/// the binary operator
|
||||
const BinaryOp op;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,77 +23,72 @@ namespace {
|
||||
using CompoundAssignmentStatementTest = TestHelper;
|
||||
|
||||
TEST_F(CompoundAssignmentStatementTest, Creation) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto op = BinaryOp::kAdd;
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto op = BinaryOp::kAdd;
|
||||
|
||||
auto* stmt = create<CompoundAssignmentStatement>(lhs, rhs, op);
|
||||
EXPECT_EQ(stmt->lhs, lhs);
|
||||
EXPECT_EQ(stmt->rhs, rhs);
|
||||
EXPECT_EQ(stmt->op, op);
|
||||
auto* stmt = create<CompoundAssignmentStatement>(lhs, rhs, op);
|
||||
EXPECT_EQ(stmt->lhs, lhs);
|
||||
EXPECT_EQ(stmt->rhs, rhs);
|
||||
EXPECT_EQ(stmt->op, op);
|
||||
}
|
||||
|
||||
TEST_F(CompoundAssignmentStatementTest, CreationWithSource) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto op = BinaryOp::kMultiply;
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto op = BinaryOp::kMultiply;
|
||||
|
||||
auto* stmt = create<CompoundAssignmentStatement>(
|
||||
Source{Source::Location{20, 2}}, lhs, rhs, op);
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* stmt = create<CompoundAssignmentStatement>(Source{Source::Location{20, 2}}, lhs, rhs, op);
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(CompoundAssignmentStatementTest, IsCompoundAssign) {
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto op = BinaryOp::kSubtract;
|
||||
auto* lhs = Expr("lhs");
|
||||
auto* rhs = Expr("rhs");
|
||||
auto op = BinaryOp::kSubtract;
|
||||
|
||||
auto* stmt = create<CompoundAssignmentStatement>(lhs, rhs, op);
|
||||
EXPECT_TRUE(stmt->Is<CompoundAssignmentStatement>());
|
||||
auto* stmt = create<CompoundAssignmentStatement>(lhs, rhs, op);
|
||||
EXPECT_TRUE(stmt->Is<CompoundAssignmentStatement>());
|
||||
}
|
||||
|
||||
TEST_F(CompoundAssignmentStatementTest, Assert_Null_LHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CompoundAssignmentStatement>(nullptr, b.Expr(1),
|
||||
BinaryOp::kAdd);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CompoundAssignmentStatement>(nullptr, b.Expr(1), BinaryOp::kAdd);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CompoundAssignmentStatementTest, Assert_Null_RHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CompoundAssignmentStatement>(b.Expr(1), nullptr,
|
||||
BinaryOp::kAdd);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<CompoundAssignmentStatement>(b.Expr(1), nullptr, BinaryOp::kAdd);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CompoundAssignmentStatementTest, Assert_DifferentProgramID_LHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CompoundAssignmentStatement>(b2.Expr("lhs"), b1.Expr("rhs"),
|
||||
BinaryOp::kAdd);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CompoundAssignmentStatement>(b2.Expr("lhs"), b1.Expr("rhs"), BinaryOp::kAdd);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(CompoundAssignmentStatementTest, Assert_DifferentProgramID_RHS) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CompoundAssignmentStatement>(b1.Expr("lhs"), b2.Expr("rhs"),
|
||||
BinaryOp::kAdd);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CompoundAssignmentStatement>(b1.Expr("lhs"), b2.Expr("rhs"), BinaryOp::kAdd);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -20,17 +20,16 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::ContinueStatement);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
ContinueStatement::ContinueStatement(ProgramID pid, const Source& src)
|
||||
: Base(pid, src) {}
|
||||
ContinueStatement::ContinueStatement(ProgramID pid, const Source& src) : Base(pid, src) {}
|
||||
|
||||
ContinueStatement::ContinueStatement(ContinueStatement&&) = default;
|
||||
|
||||
ContinueStatement::~ContinueStatement() = default;
|
||||
|
||||
const ContinueStatement* ContinueStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<ContinueStatement>(src);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<ContinueStatement>(src);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -21,20 +21,20 @@ namespace tint::ast {
|
||||
|
||||
/// An continue statement
|
||||
class ContinueStatement final : public Castable<ContinueStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
ContinueStatement(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
ContinueStatement(ContinueStatement&&);
|
||||
~ContinueStatement() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
ContinueStatement(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
ContinueStatement(ContinueStatement&&);
|
||||
~ContinueStatement() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const ContinueStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const ContinueStatement* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,15 +22,15 @@ namespace {
|
||||
using ContinueStatementTest = TestHelper;
|
||||
|
||||
TEST_F(ContinueStatementTest, Creation_WithSource) {
|
||||
auto* stmt = create<ContinueStatement>(Source{Source::Location{20, 2}});
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* stmt = create<ContinueStatement>(Source{Source::Location{20, 2}});
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(ContinueStatementTest, IsContinue) {
|
||||
auto* stmt = create<ContinueStatement>();
|
||||
EXPECT_TRUE(stmt->Is<ContinueStatement>());
|
||||
auto* stmt = create<ContinueStatement>();
|
||||
EXPECT_TRUE(stmt->Is<ContinueStatement>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace tint::ast {
|
||||
namespace {
|
||||
|
||||
bool IsValidDepthDimension(TextureDimension dim) {
|
||||
return dim == TextureDimension::k2d;
|
||||
return dim == TextureDimension::k2d;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -31,24 +31,22 @@ DepthMultisampledTexture::DepthMultisampledTexture(ProgramID pid,
|
||||
const Source& src,
|
||||
TextureDimension d)
|
||||
: Base(pid, src, d) {
|
||||
TINT_ASSERT(AST, IsValidDepthDimension(dim));
|
||||
TINT_ASSERT(AST, IsValidDepthDimension(dim));
|
||||
}
|
||||
|
||||
DepthMultisampledTexture::DepthMultisampledTexture(DepthMultisampledTexture&&) =
|
||||
default;
|
||||
DepthMultisampledTexture::DepthMultisampledTexture(DepthMultisampledTexture&&) = default;
|
||||
|
||||
DepthMultisampledTexture::~DepthMultisampledTexture() = default;
|
||||
|
||||
std::string DepthMultisampledTexture::FriendlyName(const SymbolTable&) const {
|
||||
std::ostringstream out;
|
||||
out << "texture_depth_multisampled_" << dim;
|
||||
return out.str();
|
||||
std::ostringstream out;
|
||||
out << "texture_depth_multisampled_" << dim;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
const DepthMultisampledTexture* DepthMultisampledTexture::Clone(
|
||||
CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<DepthMultisampledTexture>(src, dim);
|
||||
const DepthMultisampledTexture* DepthMultisampledTexture::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<DepthMultisampledTexture>(src, dim);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,29 +22,26 @@
|
||||
namespace tint::ast {
|
||||
|
||||
/// A multisampled depth texture type.
|
||||
class DepthMultisampledTexture final
|
||||
: public Castable<DepthMultisampledTexture, Texture> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param dim the dimensionality of the texture
|
||||
DepthMultisampledTexture(ProgramID pid,
|
||||
const Source& src,
|
||||
TextureDimension dim);
|
||||
/// Move constructor
|
||||
DepthMultisampledTexture(DepthMultisampledTexture&&);
|
||||
~DepthMultisampledTexture() override;
|
||||
class DepthMultisampledTexture final : public Castable<DepthMultisampledTexture, Texture> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param dim the dimensionality of the texture
|
||||
DepthMultisampledTexture(ProgramID pid, const Source& src, TextureDimension dim);
|
||||
/// Move constructor
|
||||
DepthMultisampledTexture(DepthMultisampledTexture&&);
|
||||
~DepthMultisampledTexture() override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const DepthMultisampledTexture* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const DepthMultisampledTexture* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,13 +22,13 @@ namespace {
|
||||
using AstDepthMultisampledTextureTest = TestHelper;
|
||||
|
||||
TEST_F(AstDepthMultisampledTextureTest, Dim) {
|
||||
auto* d = create<DepthMultisampledTexture>(TextureDimension::k2d);
|
||||
EXPECT_EQ(d->dim, TextureDimension::k2d);
|
||||
auto* d = create<DepthMultisampledTexture>(TextureDimension::k2d);
|
||||
EXPECT_EQ(d->dim, TextureDimension::k2d);
|
||||
}
|
||||
|
||||
TEST_F(AstDepthMultisampledTextureTest, FriendlyName) {
|
||||
auto* d = create<DepthMultisampledTexture>(TextureDimension::k2d);
|
||||
EXPECT_EQ(d->FriendlyName(Symbols()), "texture_depth_multisampled_2d");
|
||||
auto* d = create<DepthMultisampledTexture>(TextureDimension::k2d);
|
||||
EXPECT_EQ(d->FriendlyName(Symbols()), "texture_depth_multisampled_2d");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -22,15 +22,15 @@ namespace tint::ast {
|
||||
namespace {
|
||||
|
||||
bool IsValidDepthDimension(TextureDimension dim) {
|
||||
return dim == TextureDimension::k2d || dim == TextureDimension::k2dArray ||
|
||||
dim == TextureDimension::kCube || dim == TextureDimension::kCubeArray;
|
||||
return dim == TextureDimension::k2d || dim == TextureDimension::k2dArray ||
|
||||
dim == TextureDimension::kCube || dim == TextureDimension::kCubeArray;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DepthTexture::DepthTexture(ProgramID pid, const Source& src, TextureDimension d)
|
||||
: Base(pid, src, d) {
|
||||
TINT_ASSERT(AST, IsValidDepthDimension(dim));
|
||||
TINT_ASSERT(AST, IsValidDepthDimension(dim));
|
||||
}
|
||||
|
||||
DepthTexture::DepthTexture(DepthTexture&&) = default;
|
||||
@@ -38,14 +38,14 @@ DepthTexture::DepthTexture(DepthTexture&&) = default;
|
||||
DepthTexture::~DepthTexture() = default;
|
||||
|
||||
std::string DepthTexture::FriendlyName(const SymbolTable&) const {
|
||||
std::ostringstream out;
|
||||
out << "texture_depth_" << dim;
|
||||
return out.str();
|
||||
std::ostringstream out;
|
||||
out << "texture_depth_" << dim;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
const DepthTexture* DepthTexture::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<DepthTexture>(src, dim);
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<DepthTexture>(src, dim);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,25 +23,25 @@ namespace tint::ast {
|
||||
|
||||
/// A depth texture type.
|
||||
class DepthTexture final : public Castable<DepthTexture, Texture> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param dim the dimensionality of the texture
|
||||
DepthTexture(ProgramID pid, const Source& src, TextureDimension dim);
|
||||
/// Move constructor
|
||||
DepthTexture(DepthTexture&&);
|
||||
~DepthTexture() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param dim the dimensionality of the texture
|
||||
DepthTexture(ProgramID pid, const Source& src, TextureDimension dim);
|
||||
/// Move constructor
|
||||
DepthTexture(DepthTexture&&);
|
||||
~DepthTexture() override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const DepthTexture* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const DepthTexture* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,20 +22,20 @@ namespace {
|
||||
using AstDepthTextureTest = TestHelper;
|
||||
|
||||
TEST_F(AstDepthTextureTest, IsTexture) {
|
||||
Texture* ty = create<DepthTexture>(TextureDimension::kCube);
|
||||
EXPECT_TRUE(ty->Is<DepthTexture>());
|
||||
EXPECT_FALSE(ty->Is<SampledTexture>());
|
||||
EXPECT_FALSE(ty->Is<StorageTexture>());
|
||||
Texture* ty = create<DepthTexture>(TextureDimension::kCube);
|
||||
EXPECT_TRUE(ty->Is<DepthTexture>());
|
||||
EXPECT_FALSE(ty->Is<SampledTexture>());
|
||||
EXPECT_FALSE(ty->Is<StorageTexture>());
|
||||
}
|
||||
|
||||
TEST_F(AstDepthTextureTest, Dim) {
|
||||
auto* d = create<DepthTexture>(TextureDimension::kCube);
|
||||
EXPECT_EQ(d->dim, TextureDimension::kCube);
|
||||
auto* d = create<DepthTexture>(TextureDimension::kCube);
|
||||
EXPECT_EQ(d->dim, TextureDimension::kCube);
|
||||
}
|
||||
|
||||
TEST_F(AstDepthTextureTest, FriendlyName) {
|
||||
auto* d = create<DepthTexture>(TextureDimension::kCube);
|
||||
EXPECT_EQ(d->FriendlyName(Symbols()), "texture_depth_cube");
|
||||
auto* d = create<DepthTexture>(TextureDimension::kCube);
|
||||
EXPECT_EQ(d->FriendlyName(Symbols()), "texture_depth_cube");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -20,36 +20,33 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::DisableValidationAttribute);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
DisableValidationAttribute::DisableValidationAttribute(ProgramID pid,
|
||||
DisabledValidation val)
|
||||
DisableValidationAttribute::DisableValidationAttribute(ProgramID pid, DisabledValidation val)
|
||||
: Base(pid), validation(val) {}
|
||||
|
||||
DisableValidationAttribute::~DisableValidationAttribute() = default;
|
||||
|
||||
std::string DisableValidationAttribute::InternalName() const {
|
||||
switch (validation) {
|
||||
case DisabledValidation::kFunctionHasNoBody:
|
||||
return "disable_validation__function_has_no_body";
|
||||
case DisabledValidation::kBindingPointCollision:
|
||||
return "disable_validation__binding_point_collision";
|
||||
case DisabledValidation::kIgnoreStorageClass:
|
||||
return "disable_validation__ignore_storage_class";
|
||||
case DisabledValidation::kEntryPointParameter:
|
||||
return "disable_validation__entry_point_parameter";
|
||||
case DisabledValidation::kIgnoreConstructibleFunctionParameter:
|
||||
return "disable_validation__ignore_constructible_function_parameter";
|
||||
case DisabledValidation::kIgnoreStrideAttribute:
|
||||
return "disable_validation__ignore_stride";
|
||||
case DisabledValidation::kIgnoreInvalidPointerArgument:
|
||||
return "disable_validation__ignore_invalid_pointer_argument";
|
||||
}
|
||||
return "<invalid>";
|
||||
switch (validation) {
|
||||
case DisabledValidation::kFunctionHasNoBody:
|
||||
return "disable_validation__function_has_no_body";
|
||||
case DisabledValidation::kBindingPointCollision:
|
||||
return "disable_validation__binding_point_collision";
|
||||
case DisabledValidation::kIgnoreStorageClass:
|
||||
return "disable_validation__ignore_storage_class";
|
||||
case DisabledValidation::kEntryPointParameter:
|
||||
return "disable_validation__entry_point_parameter";
|
||||
case DisabledValidation::kIgnoreConstructibleFunctionParameter:
|
||||
return "disable_validation__ignore_constructible_function_parameter";
|
||||
case DisabledValidation::kIgnoreStrideAttribute:
|
||||
return "disable_validation__ignore_stride";
|
||||
case DisabledValidation::kIgnoreInvalidPointerArgument:
|
||||
return "disable_validation__ignore_invalid_pointer_argument";
|
||||
}
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
const DisableValidationAttribute* DisableValidationAttribute::Clone(
|
||||
CloneContext* ctx) const {
|
||||
return ctx->dst->ASTNodes().Create<DisableValidationAttribute>(ctx->dst->ID(),
|
||||
validation);
|
||||
const DisableValidationAttribute* DisableValidationAttribute::Clone(CloneContext* ctx) const {
|
||||
return ctx->dst->ASTNodes().Create<DisableValidationAttribute>(ctx->dst->ID(), validation);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -24,28 +24,28 @@ namespace tint::ast {
|
||||
/// Enumerator of validation features that can be disabled with a
|
||||
/// DisableValidationAttribute attribute.
|
||||
enum class DisabledValidation {
|
||||
/// When applied to a function, the validator will not complain there is no
|
||||
/// body to a function.
|
||||
kFunctionHasNoBody,
|
||||
/// When applied to a module-scoped variable, the validator will not complain
|
||||
/// if two resource variables have the same binding points.
|
||||
kBindingPointCollision,
|
||||
/// When applied to a variable, the validator will not complain about the
|
||||
/// declared storage class.
|
||||
kIgnoreStorageClass,
|
||||
/// When applied to an entry-point function parameter, the validator will not
|
||||
/// check for entry IO attributes.
|
||||
kEntryPointParameter,
|
||||
/// When applied to a function parameter, the validator will not
|
||||
/// check if parameter type is constructible
|
||||
kIgnoreConstructibleFunctionParameter,
|
||||
/// When applied to a member attribute, a stride attribute may be applied to
|
||||
/// non-array types.
|
||||
kIgnoreStrideAttribute,
|
||||
/// When applied to a pointer function parameter, the validator will not
|
||||
/// require a function call argument passed for that parameter to have a
|
||||
/// certain form.
|
||||
kIgnoreInvalidPointerArgument,
|
||||
/// When applied to a function, the validator will not complain there is no
|
||||
/// body to a function.
|
||||
kFunctionHasNoBody,
|
||||
/// When applied to a module-scoped variable, the validator will not complain
|
||||
/// if two resource variables have the same binding points.
|
||||
kBindingPointCollision,
|
||||
/// When applied to a variable, the validator will not complain about the
|
||||
/// declared storage class.
|
||||
kIgnoreStorageClass,
|
||||
/// When applied to an entry-point function parameter, the validator will not
|
||||
/// check for entry IO attributes.
|
||||
kEntryPointParameter,
|
||||
/// When applied to a function parameter, the validator will not
|
||||
/// check if parameter type is constructible
|
||||
kIgnoreConstructibleFunctionParameter,
|
||||
/// When applied to a member attribute, a stride attribute may be applied to
|
||||
/// non-array types.
|
||||
kIgnoreStrideAttribute,
|
||||
/// When applied to a pointer function parameter, the validator will not
|
||||
/// require a function call argument passed for that parameter to have a
|
||||
/// certain form.
|
||||
kIgnoreInvalidPointerArgument,
|
||||
};
|
||||
|
||||
/// An internal attribute used to tell the validator to ignore specific
|
||||
@@ -53,27 +53,26 @@ enum class DisabledValidation {
|
||||
/// would otherwise cause validation errors.
|
||||
class DisableValidationAttribute final
|
||||
: public Castable<DisableValidationAttribute, InternalAttribute> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param validation the validation to disable
|
||||
explicit DisableValidationAttribute(ProgramID program_id,
|
||||
DisabledValidation validation);
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param validation the validation to disable
|
||||
explicit DisableValidationAttribute(ProgramID program_id, DisabledValidation validation);
|
||||
|
||||
/// Destructor
|
||||
~DisableValidationAttribute() override;
|
||||
/// Destructor
|
||||
~DisableValidationAttribute() override;
|
||||
|
||||
/// @return a short description of the internal attribute which will be
|
||||
/// displayed in WGSL as `@internal(<name>)` (but is not parsable).
|
||||
std::string InternalName() const override;
|
||||
/// @return a short description of the internal attribute which will be
|
||||
/// displayed in WGSL as `@internal(<name>)` (but is not parsable).
|
||||
std::string InternalName() const override;
|
||||
|
||||
/// Performs a deep clone of this object using the CloneContext `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned object
|
||||
const DisableValidationAttribute* Clone(CloneContext* ctx) const override;
|
||||
/// Performs a deep clone of this object using the CloneContext `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned object
|
||||
const DisableValidationAttribute* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The validation that this attribute disables
|
||||
const DisabledValidation validation;
|
||||
/// The validation that this attribute disables
|
||||
const DisabledValidation validation;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -20,17 +20,16 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::DiscardStatement);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
DiscardStatement::DiscardStatement(ProgramID pid, const Source& src)
|
||||
: Base(pid, src) {}
|
||||
DiscardStatement::DiscardStatement(ProgramID pid, const Source& src) : Base(pid, src) {}
|
||||
|
||||
DiscardStatement::DiscardStatement(DiscardStatement&&) = default;
|
||||
|
||||
DiscardStatement::~DiscardStatement() = default;
|
||||
|
||||
const DiscardStatement* DiscardStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<DiscardStatement>(src);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<DiscardStatement>(src);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -21,20 +21,20 @@ namespace tint::ast {
|
||||
|
||||
/// A discard statement
|
||||
class DiscardStatement final : public Castable<DiscardStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
DiscardStatement(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
DiscardStatement(DiscardStatement&&);
|
||||
~DiscardStatement() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
DiscardStatement(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
DiscardStatement(DiscardStatement&&);
|
||||
~DiscardStatement() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const DiscardStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const DiscardStatement* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,25 +22,25 @@ namespace {
|
||||
using DiscardStatementTest = TestHelper;
|
||||
|
||||
TEST_F(DiscardStatementTest, Creation) {
|
||||
auto* stmt = create<DiscardStatement>();
|
||||
EXPECT_EQ(stmt->source.range.begin.line, 0u);
|
||||
EXPECT_EQ(stmt->source.range.begin.column, 0u);
|
||||
EXPECT_EQ(stmt->source.range.end.line, 0u);
|
||||
EXPECT_EQ(stmt->source.range.end.column, 0u);
|
||||
auto* stmt = create<DiscardStatement>();
|
||||
EXPECT_EQ(stmt->source.range.begin.line, 0u);
|
||||
EXPECT_EQ(stmt->source.range.begin.column, 0u);
|
||||
EXPECT_EQ(stmt->source.range.end.line, 0u);
|
||||
EXPECT_EQ(stmt->source.range.end.column, 0u);
|
||||
}
|
||||
|
||||
TEST_F(DiscardStatementTest, Creation_WithSource) {
|
||||
auto* stmt = create<DiscardStatement>(
|
||||
Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}});
|
||||
EXPECT_EQ(stmt->source.range.begin.line, 20u);
|
||||
EXPECT_EQ(stmt->source.range.begin.column, 2u);
|
||||
EXPECT_EQ(stmt->source.range.end.line, 20u);
|
||||
EXPECT_EQ(stmt->source.range.end.column, 5u);
|
||||
auto* stmt = create<DiscardStatement>(
|
||||
Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}});
|
||||
EXPECT_EQ(stmt->source.range.begin.line, 20u);
|
||||
EXPECT_EQ(stmt->source.range.begin.column, 2u);
|
||||
EXPECT_EQ(stmt->source.range.end.line, 20u);
|
||||
EXPECT_EQ(stmt->source.range.end.column, 5u);
|
||||
}
|
||||
|
||||
TEST_F(DiscardStatementTest, IsDiscard) {
|
||||
auto* stmt = create<DiscardStatement>();
|
||||
EXPECT_TRUE(stmt->Is<DiscardStatement>());
|
||||
auto* stmt = create<DiscardStatement>();
|
||||
EXPECT_TRUE(stmt->Is<DiscardStatement>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -22,26 +22,26 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::Enable);
|
||||
namespace tint::ast {
|
||||
|
||||
Enable::ExtensionKind Enable::NameToKind(const std::string& name) {
|
||||
// The reserved internal extension name for testing
|
||||
if (name == "InternalExtensionForTesting") {
|
||||
return Enable::ExtensionKind::kInternalExtensionForTesting;
|
||||
}
|
||||
// The reserved internal extension name for testing
|
||||
if (name == "InternalExtensionForTesting") {
|
||||
return Enable::ExtensionKind::kInternalExtensionForTesting;
|
||||
}
|
||||
|
||||
return Enable::ExtensionKind::kNotAnExtension;
|
||||
return Enable::ExtensionKind::kNotAnExtension;
|
||||
}
|
||||
|
||||
std::string Enable::KindToName(ExtensionKind kind) {
|
||||
switch (kind) {
|
||||
// The reserved internal extension for testing
|
||||
case ExtensionKind::kInternalExtensionForTesting:
|
||||
return "InternalExtensionForTesting";
|
||||
case ExtensionKind::kNotAnExtension:
|
||||
// Return an empty string for kNotAnExtension
|
||||
return {};
|
||||
// No default case, as this switch must cover all ExtensionKind values.
|
||||
}
|
||||
// This return shall never get hit.
|
||||
return {};
|
||||
switch (kind) {
|
||||
// The reserved internal extension for testing
|
||||
case ExtensionKind::kInternalExtensionForTesting:
|
||||
return "InternalExtensionForTesting";
|
||||
case ExtensionKind::kNotAnExtension:
|
||||
// Return an empty string for kNotAnExtension
|
||||
return {};
|
||||
// No default case, as this switch must cover all ExtensionKind values.
|
||||
}
|
||||
// This return shall never get hit.
|
||||
return {};
|
||||
}
|
||||
|
||||
Enable::Enable(ProgramID pid, const Source& src, const std::string& ext_name)
|
||||
@@ -52,7 +52,7 @@ Enable::Enable(Enable&&) = default;
|
||||
Enable::~Enable() = default;
|
||||
|
||||
const Enable* Enable::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<Enable>(src, name);
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<Enable>(src, name);
|
||||
}
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -29,55 +29,55 @@ namespace tint::ast {
|
||||
/// // Enable an extension named "f16"
|
||||
/// enable f16;
|
||||
class Enable : public Castable<Enable, Node> {
|
||||
public:
|
||||
/// The enum class identifing each supported WGSL extension
|
||||
enum class ExtensionKind {
|
||||
/// An internal reserved extension for test, named
|
||||
/// "InternalExtensionForTesting"
|
||||
kInternalExtensionForTesting = -2,
|
||||
kNotAnExtension = -1,
|
||||
};
|
||||
public:
|
||||
/// The enum class identifing each supported WGSL extension
|
||||
enum class ExtensionKind {
|
||||
/// An internal reserved extension for test, named
|
||||
/// "InternalExtensionForTesting"
|
||||
kInternalExtensionForTesting = -2,
|
||||
kNotAnExtension = -1,
|
||||
};
|
||||
|
||||
/// Convert a string of extension name into one of ExtensionKind enum value,
|
||||
/// the result will be ExtensionKind::kNotAnExtension if the name is not a
|
||||
/// known extension name. A extension node of kind kNotAnExtension must not
|
||||
/// exist in the AST tree, and using a unknown extension name in WGSL code
|
||||
/// should result in a shader-creation error.
|
||||
/// @param name string of the extension name
|
||||
/// @return the ExtensionKind enum value for the extension of given name, or
|
||||
/// kNotAnExtension if no known extension has the given name
|
||||
static ExtensionKind NameToKind(const std::string& name);
|
||||
/// Convert a string of extension name into one of ExtensionKind enum value,
|
||||
/// the result will be ExtensionKind::kNotAnExtension if the name is not a
|
||||
/// known extension name. A extension node of kind kNotAnExtension must not
|
||||
/// exist in the AST tree, and using a unknown extension name in WGSL code
|
||||
/// should result in a shader-creation error.
|
||||
/// @param name string of the extension name
|
||||
/// @return the ExtensionKind enum value for the extension of given name, or
|
||||
/// kNotAnExtension if no known extension has the given name
|
||||
static ExtensionKind NameToKind(const std::string& name);
|
||||
|
||||
/// Convert the ExtensionKind enum value to corresponding extension name
|
||||
/// string. If the given enum value is kNotAnExtension or don't have a known
|
||||
/// name, return an empty string instead.
|
||||
/// @param kind the ExtensionKind enum value
|
||||
/// @return string of the extension name corresponding to the given kind, or
|
||||
/// an empty string if the given enum value is kNotAnExtension or don't have a
|
||||
/// known corresponding name
|
||||
static std::string KindToName(ExtensionKind kind);
|
||||
/// Convert the ExtensionKind enum value to corresponding extension name
|
||||
/// string. If the given enum value is kNotAnExtension or don't have a known
|
||||
/// name, return an empty string instead.
|
||||
/// @param kind the ExtensionKind enum value
|
||||
/// @return string of the extension name corresponding to the given kind, or
|
||||
/// an empty string if the given enum value is kNotAnExtension or don't have a
|
||||
/// known corresponding name
|
||||
static std::string KindToName(ExtensionKind kind);
|
||||
|
||||
/// Create a extension
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param name the name of extension
|
||||
Enable(ProgramID pid, const Source& src, const std::string& name);
|
||||
/// Move constructor
|
||||
Enable(Enable&&);
|
||||
/// Create a extension
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param name the name of extension
|
||||
Enable(ProgramID pid, const Source& src, const std::string& name);
|
||||
/// Move constructor
|
||||
Enable(Enable&&);
|
||||
|
||||
~Enable() override;
|
||||
~Enable() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const Enable* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const Enable* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The extension name
|
||||
const std::string name;
|
||||
/// The extension name
|
||||
const std::string name;
|
||||
|
||||
/// The extension kind
|
||||
const ExtensionKind kind;
|
||||
/// The extension kind
|
||||
const ExtensionKind kind;
|
||||
};
|
||||
|
||||
/// A set of extension kinds
|
||||
|
||||
@@ -22,44 +22,37 @@ namespace {
|
||||
using AstExtensionTest = TestHelper;
|
||||
|
||||
TEST_F(AstExtensionTest, Creation) {
|
||||
auto* ext = create<Enable>(
|
||||
Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}},
|
||||
"InternalExtensionForTesting");
|
||||
EXPECT_EQ(ext->source.range.begin.line, 20u);
|
||||
EXPECT_EQ(ext->source.range.begin.column, 2u);
|
||||
EXPECT_EQ(ext->source.range.end.line, 20u);
|
||||
EXPECT_EQ(ext->source.range.end.column, 5u);
|
||||
EXPECT_EQ(ext->kind,
|
||||
ast::Enable::ExtensionKind::kInternalExtensionForTesting);
|
||||
auto* ext =
|
||||
create<Enable>(Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}},
|
||||
"InternalExtensionForTesting");
|
||||
EXPECT_EQ(ext->source.range.begin.line, 20u);
|
||||
EXPECT_EQ(ext->source.range.begin.column, 2u);
|
||||
EXPECT_EQ(ext->source.range.end.line, 20u);
|
||||
EXPECT_EQ(ext->source.range.end.column, 5u);
|
||||
EXPECT_EQ(ext->kind, ast::Enable::ExtensionKind::kInternalExtensionForTesting);
|
||||
}
|
||||
|
||||
TEST_F(AstExtensionTest, Creation_InvalidName) {
|
||||
auto* ext = create<Enable>(
|
||||
Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}},
|
||||
std::string());
|
||||
EXPECT_EQ(ext->source.range.begin.line, 20u);
|
||||
EXPECT_EQ(ext->source.range.begin.column, 2u);
|
||||
EXPECT_EQ(ext->source.range.end.line, 20u);
|
||||
EXPECT_EQ(ext->source.range.end.column, 5u);
|
||||
EXPECT_EQ(ext->kind, ast::Enable::ExtensionKind::kNotAnExtension);
|
||||
auto* ext = create<Enable>(
|
||||
Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}}, std::string());
|
||||
EXPECT_EQ(ext->source.range.begin.line, 20u);
|
||||
EXPECT_EQ(ext->source.range.begin.column, 2u);
|
||||
EXPECT_EQ(ext->source.range.end.line, 20u);
|
||||
EXPECT_EQ(ext->source.range.end.column, 5u);
|
||||
EXPECT_EQ(ext->kind, ast::Enable::ExtensionKind::kNotAnExtension);
|
||||
}
|
||||
|
||||
TEST_F(AstExtensionTest, NameToKind_InvalidName) {
|
||||
EXPECT_EQ(ast::Enable::NameToKind(std::string()),
|
||||
ast::Enable::ExtensionKind::kNotAnExtension);
|
||||
EXPECT_EQ(ast::Enable::NameToKind("__ImpossibleExtensionName"),
|
||||
ast::Enable::ExtensionKind::kNotAnExtension);
|
||||
EXPECT_EQ(ast::Enable::NameToKind("123"),
|
||||
ast::Enable::ExtensionKind::kNotAnExtension);
|
||||
EXPECT_EQ(ast::Enable::NameToKind(std::string()), ast::Enable::ExtensionKind::kNotAnExtension);
|
||||
EXPECT_EQ(ast::Enable::NameToKind("__ImpossibleExtensionName"),
|
||||
ast::Enable::ExtensionKind::kNotAnExtension);
|
||||
EXPECT_EQ(ast::Enable::NameToKind("123"), ast::Enable::ExtensionKind::kNotAnExtension);
|
||||
}
|
||||
|
||||
TEST_F(AstExtensionTest, KindToName) {
|
||||
EXPECT_EQ(ast::Enable::KindToName(
|
||||
ast::Enable::ExtensionKind::kInternalExtensionForTesting),
|
||||
"InternalExtensionForTesting");
|
||||
EXPECT_EQ(
|
||||
ast::Enable::KindToName(ast::Enable::ExtensionKind::kNotAnExtension),
|
||||
std::string());
|
||||
EXPECT_EQ(ast::Enable::KindToName(ast::Enable::ExtensionKind::kInternalExtensionForTesting),
|
||||
"InternalExtensionForTesting");
|
||||
EXPECT_EQ(ast::Enable::KindToName(ast::Enable::ExtensionKind::kNotAnExtension), std::string());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -25,16 +25,16 @@ namespace tint::ast {
|
||||
|
||||
/// Base expression class
|
||||
class Expression : public Castable<Expression, Node> {
|
||||
public:
|
||||
~Expression() override;
|
||||
public:
|
||||
~Expression() override;
|
||||
|
||||
protected:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
Expression(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
Expression(Expression&&);
|
||||
protected:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
Expression(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
Expression(Expression&&);
|
||||
};
|
||||
|
||||
/// A list of expressions
|
||||
|
||||
@@ -29,11 +29,11 @@ ExternalTexture::ExternalTexture(ExternalTexture&&) = default;
|
||||
ExternalTexture::~ExternalTexture() = default;
|
||||
|
||||
std::string ExternalTexture::FriendlyName(const SymbolTable&) const {
|
||||
return "texture_external";
|
||||
return "texture_external";
|
||||
}
|
||||
|
||||
const ExternalTexture* ExternalTexture::Clone(CloneContext* ctx) const {
|
||||
return ctx->dst->create<ExternalTexture>();
|
||||
return ctx->dst->create<ExternalTexture>();
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,25 +23,25 @@ namespace tint::ast {
|
||||
|
||||
/// An external texture type
|
||||
class ExternalTexture final : public Castable<ExternalTexture, Texture> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
ExternalTexture(ProgramID pid, const Source& src);
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
ExternalTexture(ProgramID pid, const Source& src);
|
||||
|
||||
/// Move constructor
|
||||
ExternalTexture(ExternalTexture&&);
|
||||
~ExternalTexture() override;
|
||||
/// Move constructor
|
||||
ExternalTexture(ExternalTexture&&);
|
||||
~ExternalTexture() override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const ExternalTexture* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const ExternalTexture* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,22 +22,22 @@ namespace {
|
||||
using AstExternalTextureTest = TestHelper;
|
||||
|
||||
TEST_F(AstExternalTextureTest, IsTexture) {
|
||||
Texture* ty = create<ExternalTexture>();
|
||||
EXPECT_FALSE(ty->Is<DepthTexture>());
|
||||
EXPECT_TRUE(ty->Is<ExternalTexture>());
|
||||
EXPECT_FALSE(ty->Is<MultisampledTexture>());
|
||||
EXPECT_FALSE(ty->Is<SampledTexture>());
|
||||
EXPECT_FALSE(ty->Is<StorageTexture>());
|
||||
Texture* ty = create<ExternalTexture>();
|
||||
EXPECT_FALSE(ty->Is<DepthTexture>());
|
||||
EXPECT_TRUE(ty->Is<ExternalTexture>());
|
||||
EXPECT_FALSE(ty->Is<MultisampledTexture>());
|
||||
EXPECT_FALSE(ty->Is<SampledTexture>());
|
||||
EXPECT_FALSE(ty->Is<StorageTexture>());
|
||||
}
|
||||
|
||||
TEST_F(AstExternalTextureTest, Dim) {
|
||||
auto* ty = create<ExternalTexture>();
|
||||
EXPECT_EQ(ty->dim, ast::TextureDimension::k2d);
|
||||
auto* ty = create<ExternalTexture>();
|
||||
EXPECT_EQ(ty->dim, ast::TextureDimension::k2d);
|
||||
}
|
||||
|
||||
TEST_F(AstExternalTextureTest, FriendlyName) {
|
||||
auto* ty = create<ExternalTexture>();
|
||||
EXPECT_EQ(ty->FriendlyName(Symbols()), "texture_external");
|
||||
auto* ty = create<ExternalTexture>();
|
||||
EXPECT_EQ(ty->FriendlyName(Symbols()), "texture_external");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -27,12 +27,12 @@ F32::F32(F32&&) = default;
|
||||
F32::~F32() = default;
|
||||
|
||||
std::string F32::FriendlyName(const SymbolTable&) const {
|
||||
return "f32";
|
||||
return "f32";
|
||||
}
|
||||
|
||||
const F32* F32::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<F32>(src);
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<F32>(src);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,24 +23,24 @@ namespace tint::ast {
|
||||
|
||||
/// A float 32 type
|
||||
class F32 final : public Castable<F32, Type> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
F32(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
F32(F32&&);
|
||||
~F32() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
F32(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
F32(F32&&);
|
||||
~F32() override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const F32* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const F32* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace {
|
||||
using AstF32Test = TestHelper;
|
||||
|
||||
TEST_F(AstF32Test, FriendlyName) {
|
||||
auto* f = create<F32>();
|
||||
EXPECT_EQ(f->FriendlyName(Symbols()), "f32");
|
||||
auto* f = create<F32>();
|
||||
EXPECT_EQ(f->FriendlyName(Symbols()), "f32");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -20,18 +20,16 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::FallthroughStatement);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
FallthroughStatement::FallthroughStatement(ProgramID pid, const Source& src)
|
||||
: Base(pid, src) {}
|
||||
FallthroughStatement::FallthroughStatement(ProgramID pid, const Source& src) : Base(pid, src) {}
|
||||
|
||||
FallthroughStatement::FallthroughStatement(FallthroughStatement&&) = default;
|
||||
|
||||
FallthroughStatement::~FallthroughStatement() = default;
|
||||
|
||||
const FallthroughStatement* FallthroughStatement::Clone(
|
||||
CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<FallthroughStatement>(src);
|
||||
const FallthroughStatement* FallthroughStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<FallthroughStatement>(src);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -20,22 +20,21 @@
|
||||
namespace tint::ast {
|
||||
|
||||
/// An fallthrough statement
|
||||
class FallthroughStatement final
|
||||
: public Castable<FallthroughStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
FallthroughStatement(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
FallthroughStatement(FallthroughStatement&&);
|
||||
~FallthroughStatement() override;
|
||||
class FallthroughStatement final : public Castable<FallthroughStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
FallthroughStatement(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
FallthroughStatement(FallthroughStatement&&);
|
||||
~FallthroughStatement() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const FallthroughStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const FallthroughStatement* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,23 +22,23 @@ namespace {
|
||||
using FallthroughStatementTest = TestHelper;
|
||||
|
||||
TEST_F(FallthroughStatementTest, Creation) {
|
||||
auto* stmt = create<FallthroughStatement>();
|
||||
EXPECT_EQ(stmt->source.range.begin.line, 0u);
|
||||
EXPECT_EQ(stmt->source.range.begin.column, 0u);
|
||||
EXPECT_EQ(stmt->source.range.end.line, 0u);
|
||||
EXPECT_EQ(stmt->source.range.end.column, 0u);
|
||||
auto* stmt = create<FallthroughStatement>();
|
||||
EXPECT_EQ(stmt->source.range.begin.line, 0u);
|
||||
EXPECT_EQ(stmt->source.range.begin.column, 0u);
|
||||
EXPECT_EQ(stmt->source.range.end.line, 0u);
|
||||
EXPECT_EQ(stmt->source.range.end.column, 0u);
|
||||
}
|
||||
|
||||
TEST_F(FallthroughStatementTest, Creation_WithSource) {
|
||||
auto* stmt = create<FallthroughStatement>(Source{Source::Location{20, 2}});
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* stmt = create<FallthroughStatement>(Source{Source::Location{20, 2}});
|
||||
auto src = stmt->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(FallthroughStatementTest, IsFallthrough) {
|
||||
auto* stmt = create<FallthroughStatement>();
|
||||
EXPECT_TRUE(stmt->Is<FallthroughStatement>());
|
||||
auto* stmt = create<FallthroughStatement>();
|
||||
EXPECT_TRUE(stmt->Is<FallthroughStatement>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -22,18 +22,15 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::FloatLiteralExpression);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
FloatLiteralExpression::FloatLiteralExpression(ProgramID pid,
|
||||
const Source& src,
|
||||
float val)
|
||||
FloatLiteralExpression::FloatLiteralExpression(ProgramID pid, const Source& src, float val)
|
||||
: Base(pid, src), value(val) {}
|
||||
|
||||
FloatLiteralExpression::~FloatLiteralExpression() = default;
|
||||
|
||||
const FloatLiteralExpression* FloatLiteralExpression::Clone(
|
||||
CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<FloatLiteralExpression>(src, value);
|
||||
const FloatLiteralExpression* FloatLiteralExpression::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<FloatLiteralExpression>(src, value);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,24 +22,23 @@
|
||||
namespace tint::ast {
|
||||
|
||||
/// A float literal
|
||||
class FloatLiteralExpression final
|
||||
: public Castable<FloatLiteralExpression, LiteralExpression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param value the float literals value
|
||||
FloatLiteralExpression(ProgramID pid, const Source& src, float value);
|
||||
~FloatLiteralExpression() override;
|
||||
class FloatLiteralExpression final : public Castable<FloatLiteralExpression, LiteralExpression> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param value the float literals value
|
||||
FloatLiteralExpression(ProgramID pid, const Source& src, float value);
|
||||
~FloatLiteralExpression() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const FloatLiteralExpression* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const FloatLiteralExpression* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The float literal value
|
||||
const float value;
|
||||
/// The float literal value
|
||||
const float value;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -20,9 +20,9 @@ namespace {
|
||||
using FloatLiteralExpressionTest = TestHelper;
|
||||
|
||||
TEST_F(FloatLiteralExpressionTest, Value) {
|
||||
auto* f = create<FloatLiteralExpression>(47.2f);
|
||||
ASSERT_TRUE(f->Is<FloatLiteralExpression>());
|
||||
EXPECT_EQ(f->value, 47.2f);
|
||||
auto* f = create<FloatLiteralExpression>(47.2f);
|
||||
ASSERT_TRUE(f->Is<FloatLiteralExpression>());
|
||||
EXPECT_EQ(f->value, 47.2f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -26,17 +26,13 @@ ForLoopStatement::ForLoopStatement(ProgramID pid,
|
||||
const Expression* cond,
|
||||
const Statement* cont,
|
||||
const BlockStatement* b)
|
||||
: Base(pid, src),
|
||||
initializer(init),
|
||||
condition(cond),
|
||||
continuing(cont),
|
||||
body(b) {
|
||||
TINT_ASSERT(AST, body);
|
||||
: Base(pid, src), initializer(init), condition(cond), continuing(cont), body(b) {
|
||||
TINT_ASSERT(AST, body);
|
||||
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, initializer, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, initializer, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
||||
}
|
||||
|
||||
ForLoopStatement::ForLoopStatement(ForLoopStatement&&) = default;
|
||||
@@ -44,14 +40,14 @@ ForLoopStatement::ForLoopStatement(ForLoopStatement&&) = default;
|
||||
ForLoopStatement::~ForLoopStatement() = default;
|
||||
|
||||
const ForLoopStatement* ForLoopStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
|
||||
auto* init = ctx->Clone(initializer);
|
||||
auto* cond = ctx->Clone(condition);
|
||||
auto* cont = ctx->Clone(continuing);
|
||||
auto* b = ctx->Clone(body);
|
||||
return ctx->dst->create<ForLoopStatement>(src, init, cond, cont, b);
|
||||
auto* init = ctx->Clone(initializer);
|
||||
auto* cond = ctx->Clone(condition);
|
||||
auto* cont = ctx->Clone(continuing);
|
||||
auto* b = ctx->Clone(body);
|
||||
return ctx->dst->create<ForLoopStatement>(src, init, cond, cont, b);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,41 +23,41 @@ class Expression;
|
||||
|
||||
/// A for loop statement
|
||||
class ForLoopStatement final : public Castable<ForLoopStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the for loop statement source
|
||||
/// @param initializer the optional loop initializer statement
|
||||
/// @param condition the optional loop condition expression
|
||||
/// @param continuing the optional continuing statement
|
||||
/// @param body the loop body
|
||||
ForLoopStatement(ProgramID program_id,
|
||||
Source const& source,
|
||||
const Statement* initializer,
|
||||
const Expression* condition,
|
||||
const Statement* continuing,
|
||||
const BlockStatement* body);
|
||||
/// Move constructor
|
||||
ForLoopStatement(ForLoopStatement&&);
|
||||
~ForLoopStatement() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the for loop statement source
|
||||
/// @param initializer the optional loop initializer statement
|
||||
/// @param condition the optional loop condition expression
|
||||
/// @param continuing the optional continuing statement
|
||||
/// @param body the loop body
|
||||
ForLoopStatement(ProgramID program_id,
|
||||
Source const& source,
|
||||
const Statement* initializer,
|
||||
const Expression* condition,
|
||||
const Statement* continuing,
|
||||
const BlockStatement* body);
|
||||
/// Move constructor
|
||||
ForLoopStatement(ForLoopStatement&&);
|
||||
~ForLoopStatement() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const ForLoopStatement* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const ForLoopStatement* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The initializer statement
|
||||
const Statement* const initializer;
|
||||
/// The initializer statement
|
||||
const Statement* const initializer;
|
||||
|
||||
/// The condition expression
|
||||
const Expression* const condition;
|
||||
/// The condition expression
|
||||
const Expression* const condition;
|
||||
|
||||
/// The continuing statement
|
||||
const Statement* const continuing;
|
||||
/// The continuing statement
|
||||
const Statement* const continuing;
|
||||
|
||||
/// The loop body block
|
||||
const BlockStatement* const body;
|
||||
/// The loop body block
|
||||
const BlockStatement* const body;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,80 +22,79 @@ namespace {
|
||||
using ForLoopStatementTest = TestHelper;
|
||||
|
||||
TEST_F(ForLoopStatementTest, Creation) {
|
||||
auto* init = Decl(Var("i", ty.u32()));
|
||||
auto* cond =
|
||||
create<BinaryExpression>(BinaryOp::kLessThan, Expr("i"), Expr(5u));
|
||||
auto* cont = Assign("i", Add("i", 1));
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(init, cond, cont, body);
|
||||
auto* init = Decl(Var("i", ty.u32()));
|
||||
auto* cond = create<BinaryExpression>(BinaryOp::kLessThan, Expr("i"), Expr(5u));
|
||||
auto* cont = Assign("i", Add("i", 1));
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(init, cond, cont, body);
|
||||
|
||||
EXPECT_EQ(l->initializer, init);
|
||||
EXPECT_EQ(l->condition, cond);
|
||||
EXPECT_EQ(l->continuing, cont);
|
||||
EXPECT_EQ(l->body, body);
|
||||
EXPECT_EQ(l->initializer, init);
|
||||
EXPECT_EQ(l->condition, cond);
|
||||
EXPECT_EQ(l->continuing, cont);
|
||||
EXPECT_EQ(l->body, body);
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Creation_WithSource) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(Source{{20u, 2u}}, nullptr, nullptr, nullptr, body);
|
||||
auto src = l->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(Source{{20u, 2u}}, nullptr, nullptr, nullptr, body);
|
||||
auto src = l->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Creation_Null_InitCondCont) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(nullptr, nullptr, nullptr, body);
|
||||
EXPECT_EQ(l->body, body);
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(nullptr, nullptr, nullptr, body);
|
||||
EXPECT_EQ(l->body, body);
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_Null_Body) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.For(nullptr, nullptr, nullptr, nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.For(nullptr, nullptr, nullptr, nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_DifferentProgramID_Initializer) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(b2.Block(), nullptr, nullptr, b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(b2.Block(), nullptr, nullptr, b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_DifferentProgramID_Condition) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, b2.Expr(true), nullptr, b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, b2.Expr(true), nullptr, b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_DifferentProgramID_Continuing) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, nullptr, b2.Block(), b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, nullptr, b2.Block(), b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_DifferentProgramID_Body) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, nullptr, nullptr, b2.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, nullptr, nullptr, b2.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -37,20 +37,20 @@ Function::Function(ProgramID pid,
|
||||
body(b),
|
||||
attributes(std::move(attrs)),
|
||||
return_type_attributes(std::move(return_type_attrs)) {
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
||||
for (auto* param : params) {
|
||||
TINT_ASSERT(AST, param && param->is_const);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, param, program_id);
|
||||
}
|
||||
TINT_ASSERT(AST, symbol.IsValid());
|
||||
TINT_ASSERT(AST, return_type);
|
||||
for (auto* attr : attributes) {
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
|
||||
}
|
||||
for (auto* attr : return_type_attributes) {
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
|
||||
}
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
|
||||
for (auto* param : params) {
|
||||
TINT_ASSERT(AST, param && param->is_const);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, param, program_id);
|
||||
}
|
||||
TINT_ASSERT(AST, symbol.IsValid());
|
||||
TINT_ASSERT(AST, return_type);
|
||||
for (auto* attr : attributes) {
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
|
||||
}
|
||||
for (auto* attr : return_type_attributes) {
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
|
||||
}
|
||||
}
|
||||
|
||||
Function::Function(Function&&) = default;
|
||||
@@ -58,49 +58,49 @@ Function::Function(Function&&) = default;
|
||||
Function::~Function() = default;
|
||||
|
||||
PipelineStage Function::PipelineStage() const {
|
||||
if (auto* stage = GetAttribute<StageAttribute>(attributes)) {
|
||||
return stage->stage;
|
||||
}
|
||||
return PipelineStage::kNone;
|
||||
if (auto* stage = GetAttribute<StageAttribute>(attributes)) {
|
||||
return stage->stage;
|
||||
}
|
||||
return PipelineStage::kNone;
|
||||
}
|
||||
|
||||
const Function* Function::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto sym = ctx->Clone(symbol);
|
||||
auto p = ctx->Clone(params);
|
||||
auto* ret = ctx->Clone(return_type);
|
||||
auto* b = ctx->Clone(body);
|
||||
auto attrs = ctx->Clone(attributes);
|
||||
auto ret_attrs = ctx->Clone(return_type_attributes);
|
||||
return ctx->dst->create<Function>(src, sym, p, ret, b, attrs, ret_attrs);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto sym = ctx->Clone(symbol);
|
||||
auto p = ctx->Clone(params);
|
||||
auto* ret = ctx->Clone(return_type);
|
||||
auto* b = ctx->Clone(body);
|
||||
auto attrs = ctx->Clone(attributes);
|
||||
auto ret_attrs = ctx->Clone(return_type_attributes);
|
||||
return ctx->dst->create<Function>(src, sym, p, ret, b, attrs, ret_attrs);
|
||||
}
|
||||
|
||||
const Function* FunctionList::Find(Symbol sym) const {
|
||||
for (auto* func : *this) {
|
||||
if (func->symbol == sym) {
|
||||
return func;
|
||||
for (auto* func : *this) {
|
||||
if (func->symbol == sym) {
|
||||
return func;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Function* FunctionList::Find(Symbol sym, PipelineStage stage) const {
|
||||
for (auto* func : *this) {
|
||||
if (func->symbol == sym && func->PipelineStage() == stage) {
|
||||
return func;
|
||||
for (auto* func : *this) {
|
||||
if (func->symbol == sym && func->PipelineStage() == stage) {
|
||||
return func;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool FunctionList::HasStage(ast::PipelineStage stage) const {
|
||||
for (auto* func : *this) {
|
||||
if (func->PipelineStage() == stage) {
|
||||
return true;
|
||||
for (auto* func : *this) {
|
||||
if (func->PipelineStage() == stage) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -33,82 +33,82 @@ namespace tint::ast {
|
||||
|
||||
/// A Function statement.
|
||||
class Function final : public Castable<Function, Node> {
|
||||
public:
|
||||
/// Create a function
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the variable source
|
||||
/// @param symbol the function symbol
|
||||
/// @param params the function parameters
|
||||
/// @param return_type the return type
|
||||
/// @param body the function body
|
||||
/// @param attributes the function attributes
|
||||
/// @param return_type_attributes the return type attributes
|
||||
Function(ProgramID program_id,
|
||||
const Source& source,
|
||||
Symbol symbol,
|
||||
VariableList params,
|
||||
const Type* return_type,
|
||||
const BlockStatement* body,
|
||||
AttributeList attributes,
|
||||
AttributeList return_type_attributes);
|
||||
/// Move constructor
|
||||
Function(Function&&);
|
||||
public:
|
||||
/// Create a function
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the variable source
|
||||
/// @param symbol the function symbol
|
||||
/// @param params the function parameters
|
||||
/// @param return_type the return type
|
||||
/// @param body the function body
|
||||
/// @param attributes the function attributes
|
||||
/// @param return_type_attributes the return type attributes
|
||||
Function(ProgramID program_id,
|
||||
const Source& source,
|
||||
Symbol symbol,
|
||||
VariableList params,
|
||||
const Type* return_type,
|
||||
const BlockStatement* body,
|
||||
AttributeList attributes,
|
||||
AttributeList return_type_attributes);
|
||||
/// Move constructor
|
||||
Function(Function&&);
|
||||
|
||||
~Function() override;
|
||||
~Function() override;
|
||||
|
||||
/// @returns the functions pipeline stage or None if not set
|
||||
ast::PipelineStage PipelineStage() const;
|
||||
/// @returns the functions pipeline stage or None if not set
|
||||
ast::PipelineStage PipelineStage() const;
|
||||
|
||||
/// @returns true if this function is an entry point
|
||||
bool IsEntryPoint() const { return PipelineStage() != PipelineStage::kNone; }
|
||||
/// @returns true if this function is an entry point
|
||||
bool IsEntryPoint() const { return PipelineStage() != PipelineStage::kNone; }
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const Function* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const Function* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The function symbol
|
||||
const Symbol symbol;
|
||||
/// The function symbol
|
||||
const Symbol symbol;
|
||||
|
||||
/// The function params
|
||||
const VariableList params;
|
||||
/// The function params
|
||||
const VariableList params;
|
||||
|
||||
/// The function return type
|
||||
const Type* const return_type;
|
||||
/// The function return type
|
||||
const Type* const return_type;
|
||||
|
||||
/// The function body
|
||||
const BlockStatement* const body;
|
||||
/// The function body
|
||||
const BlockStatement* const body;
|
||||
|
||||
/// The attributes attached to this function
|
||||
const AttributeList attributes;
|
||||
/// The attributes attached to this function
|
||||
const AttributeList attributes;
|
||||
|
||||
/// The attributes attached to the function return type.
|
||||
const AttributeList return_type_attributes;
|
||||
/// The attributes attached to the function return type.
|
||||
const AttributeList return_type_attributes;
|
||||
};
|
||||
|
||||
/// A list of functions
|
||||
class FunctionList : public std::vector<const Function*> {
|
||||
public:
|
||||
/// Appends f to the end of the list
|
||||
/// @param f the function to append to this list
|
||||
void Add(const Function* f) { this->emplace_back(f); }
|
||||
public:
|
||||
/// Appends f to the end of the list
|
||||
/// @param f the function to append to this list
|
||||
void Add(const Function* f) { this->emplace_back(f); }
|
||||
|
||||
/// Returns the function with the given name
|
||||
/// @param sym the function symbol to search for
|
||||
/// @returns the associated function or nullptr if none exists
|
||||
const Function* Find(Symbol sym) const;
|
||||
/// Returns the function with the given name
|
||||
/// @param sym the function symbol to search for
|
||||
/// @returns the associated function or nullptr if none exists
|
||||
const Function* Find(Symbol sym) const;
|
||||
|
||||
/// Returns the function with the given name
|
||||
/// @param sym the function symbol to search for
|
||||
/// @param stage the pipeline stage
|
||||
/// @returns the associated function or nullptr if none exists
|
||||
const Function* Find(Symbol sym, PipelineStage stage) const;
|
||||
/// Returns the function with the given name
|
||||
/// @param sym the function symbol to search for
|
||||
/// @param stage the pipeline stage
|
||||
/// @returns the associated function or nullptr if none exists
|
||||
const Function* Find(Symbol sym, PipelineStage stage) const;
|
||||
|
||||
/// @param stage the pipeline stage
|
||||
/// @returns true if the Builder contains an entrypoint function with
|
||||
/// the given stage
|
||||
bool HasStage(PipelineStage stage) const;
|
||||
/// @param stage the pipeline stage
|
||||
/// @returns true if the Builder contains an entrypoint function with
|
||||
/// the given stage
|
||||
bool HasStage(PipelineStage stage) const;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -24,170 +24,165 @@ namespace {
|
||||
using FunctionTest = TestHelper;
|
||||
|
||||
TEST_F(FunctionTest, Creation) {
|
||||
VariableList params;
|
||||
params.push_back(Param("var", ty.i32()));
|
||||
auto* var = params[0];
|
||||
VariableList params;
|
||||
params.push_back(Param("var", ty.i32()));
|
||||
auto* var = params[0];
|
||||
|
||||
auto* f = Func("func", params, ty.void_(), StatementList{}, AttributeList{});
|
||||
EXPECT_EQ(f->symbol, Symbols().Get("func"));
|
||||
ASSERT_EQ(f->params.size(), 1u);
|
||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||
EXPECT_EQ(f->params[0], var);
|
||||
auto* f = Func("func", params, ty.void_(), StatementList{}, AttributeList{});
|
||||
EXPECT_EQ(f->symbol, Symbols().Get("func"));
|
||||
ASSERT_EQ(f->params.size(), 1u);
|
||||
EXPECT_TRUE(f->return_type->Is<ast::Void>());
|
||||
EXPECT_EQ(f->params[0], var);
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Creation_WithSource) {
|
||||
VariableList params;
|
||||
params.push_back(Param("var", ty.i32()));
|
||||
VariableList params;
|
||||
params.push_back(Param("var", ty.i32()));
|
||||
|
||||
auto* f = Func(Source{Source::Location{20, 2}}, "func", params, ty.void_(),
|
||||
StatementList{}, AttributeList{});
|
||||
auto src = f->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
auto* f = Func(Source{Source::Location{20, 2}}, "func", params, ty.void_(), StatementList{},
|
||||
AttributeList{});
|
||||
auto src = f->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Assert_InvalidName) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.Func("", VariableList{}, b.ty.void_(), StatementList{},
|
||||
AttributeList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.Func("", VariableList{}, b.ty.void_(), StatementList{}, AttributeList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Assert_Null_ReturnType) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.Func("f", VariableList{}, nullptr, StatementList{}, AttributeList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.Func("f", VariableList{}, nullptr, StatementList{}, AttributeList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Assert_Null_Param) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
VariableList params;
|
||||
params.push_back(b.Param("var", b.ty.i32()));
|
||||
params.push_back(nullptr);
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
VariableList params;
|
||||
params.push_back(b.Param("var", b.ty.i32()));
|
||||
params.push_back(nullptr);
|
||||
|
||||
b.Func("f", params, b.ty.void_(), StatementList{}, AttributeList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
b.Func("f", params, b.ty.void_(), StatementList{}, AttributeList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Assert_DifferentProgramID_Symbol) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.Func(b2.Sym("func"), VariableList{}, b1.ty.void_(), StatementList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.Func(b2.Sym("func"), VariableList{}, b1.ty.void_(), StatementList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Assert_DifferentProgramID_Param) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.Func("func", VariableList{b2.Param("var", b2.ty.i32())},
|
||||
b1.ty.void_(), StatementList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.Func("func", VariableList{b2.Param("var", b2.ty.i32())}, b1.ty.void_(),
|
||||
StatementList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Assert_DifferentProgramID_Attr) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.Func("func", VariableList{}, b1.ty.void_(), StatementList{},
|
||||
AttributeList{
|
||||
b2.WorkgroupSize(2, 4, 6),
|
||||
});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.Func("func", VariableList{}, b1.ty.void_(), StatementList{},
|
||||
AttributeList{
|
||||
b2.WorkgroupSize(2, 4, 6),
|
||||
});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Assert_DifferentProgramID_ReturnAttr) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.Func("func", VariableList{}, b1.ty.void_(), StatementList{},
|
||||
AttributeList{},
|
||||
AttributeList{
|
||||
b2.WorkgroupSize(2, 4, 6),
|
||||
});
|
||||
},
|
||||
"internal compiler error");
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.Func("func", VariableList{}, b1.ty.void_(), StatementList{}, AttributeList{},
|
||||
AttributeList{
|
||||
b2.WorkgroupSize(2, 4, 6),
|
||||
});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(FunctionTest, Assert_NonConstParam) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
VariableList params;
|
||||
params.push_back(b.Var("var", b.ty.i32(), ast::StorageClass::kNone));
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
VariableList params;
|
||||
params.push_back(b.Var("var", b.ty.i32(), ast::StorageClass::kNone));
|
||||
|
||||
b.Func("f", params, b.ty.void_(), StatementList{}, AttributeList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
b.Func("f", params, b.ty.void_(), StatementList{}, AttributeList{});
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
using FunctionListTest = TestHelper;
|
||||
|
||||
TEST_F(FunctionListTest, FindSymbol) {
|
||||
auto* func = Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{});
|
||||
FunctionList list;
|
||||
list.Add(func);
|
||||
EXPECT_EQ(func, list.Find(Symbols().Register("main")));
|
||||
auto* func = Func("main", VariableList{}, ty.f32(), StatementList{}, ast::AttributeList{});
|
||||
FunctionList list;
|
||||
list.Add(func);
|
||||
EXPECT_EQ(func, list.Find(Symbols().Register("main")));
|
||||
}
|
||||
|
||||
TEST_F(FunctionListTest, FindSymbolMissing) {
|
||||
FunctionList list;
|
||||
EXPECT_EQ(nullptr, list.Find(Symbols().Register("Missing")));
|
||||
FunctionList list;
|
||||
EXPECT_EQ(nullptr, list.Find(Symbols().Register("Missing")));
|
||||
}
|
||||
|
||||
TEST_F(FunctionListTest, FindSymbolStage) {
|
||||
auto* fs = Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{
|
||||
Stage(PipelineStage::kFragment),
|
||||
});
|
||||
auto* vs = Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{
|
||||
Stage(PipelineStage::kVertex),
|
||||
});
|
||||
FunctionList list;
|
||||
list.Add(fs);
|
||||
list.Add(vs);
|
||||
EXPECT_EQ(fs,
|
||||
list.Find(Symbols().Register("main"), PipelineStage::kFragment));
|
||||
EXPECT_EQ(vs, list.Find(Symbols().Register("main"), PipelineStage::kVertex));
|
||||
auto* fs = Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{
|
||||
Stage(PipelineStage::kFragment),
|
||||
});
|
||||
auto* vs = Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{
|
||||
Stage(PipelineStage::kVertex),
|
||||
});
|
||||
FunctionList list;
|
||||
list.Add(fs);
|
||||
list.Add(vs);
|
||||
EXPECT_EQ(fs, list.Find(Symbols().Register("main"), PipelineStage::kFragment));
|
||||
EXPECT_EQ(vs, list.Find(Symbols().Register("main"), PipelineStage::kVertex));
|
||||
}
|
||||
|
||||
TEST_F(FunctionListTest, FindSymbolStageMissing) {
|
||||
FunctionList list;
|
||||
list.Add(Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{
|
||||
Stage(PipelineStage::kFragment),
|
||||
}));
|
||||
EXPECT_EQ(nullptr,
|
||||
list.Find(Symbols().Register("main"), PipelineStage::kVertex));
|
||||
FunctionList list;
|
||||
list.Add(Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{
|
||||
Stage(PipelineStage::kFragment),
|
||||
}));
|
||||
EXPECT_EQ(nullptr, list.Find(Symbols().Register("main"), PipelineStage::kVertex));
|
||||
}
|
||||
|
||||
TEST_F(FunctionListTest, HasStage) {
|
||||
FunctionList list;
|
||||
list.Add(Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{
|
||||
Stage(PipelineStage::kFragment),
|
||||
}));
|
||||
EXPECT_TRUE(list.HasStage(PipelineStage::kFragment));
|
||||
EXPECT_FALSE(list.HasStage(PipelineStage::kVertex));
|
||||
FunctionList list;
|
||||
list.Add(Func("main", VariableList{}, ty.f32(), StatementList{},
|
||||
ast::AttributeList{
|
||||
Stage(PipelineStage::kFragment),
|
||||
}));
|
||||
EXPECT_TRUE(list.HasStage(PipelineStage::kFragment));
|
||||
EXPECT_FALSE(list.HasStage(PipelineStage::kVertex));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -28,13 +28,13 @@ GroupAttribute::GroupAttribute(ProgramID pid, const Source& src, uint32_t val)
|
||||
GroupAttribute::~GroupAttribute() = default;
|
||||
|
||||
std::string GroupAttribute::Name() const {
|
||||
return "group";
|
||||
return "group";
|
||||
}
|
||||
|
||||
const GroupAttribute* GroupAttribute::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<GroupAttribute>(src, value);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<GroupAttribute>(src, value);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,25 +23,25 @@ namespace tint::ast {
|
||||
|
||||
/// A group attribute
|
||||
class GroupAttribute final : public Castable<GroupAttribute, Attribute> {
|
||||
public:
|
||||
/// constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param value the group value
|
||||
GroupAttribute(ProgramID pid, const Source& src, uint32_t value);
|
||||
~GroupAttribute() override;
|
||||
public:
|
||||
/// constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param value the group value
|
||||
GroupAttribute(ProgramID pid, const Source& src, uint32_t value);
|
||||
~GroupAttribute() override;
|
||||
|
||||
/// @returns the WGSL name for the attribute
|
||||
std::string Name() const override;
|
||||
/// @returns the WGSL name for the attribute
|
||||
std::string Name() const override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const GroupAttribute* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const GroupAttribute* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The group value
|
||||
const uint32_t value;
|
||||
/// The group value
|
||||
const uint32_t value;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace {
|
||||
using GroupAttributeTest = TestHelper;
|
||||
|
||||
TEST_F(GroupAttributeTest, Creation) {
|
||||
auto* d = create<GroupAttribute>(2);
|
||||
EXPECT_EQ(2u, d->value);
|
||||
auto* d = create<GroupAttribute>(2);
|
||||
EXPECT_EQ(2u, d->value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -27,12 +27,12 @@ I32::I32(I32&&) = default;
|
||||
I32::~I32() = default;
|
||||
|
||||
std::string I32::FriendlyName(const SymbolTable&) const {
|
||||
return "i32";
|
||||
return "i32";
|
||||
}
|
||||
|
||||
const I32* I32::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<I32>(src);
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<I32>(src);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -23,24 +23,24 @@ namespace tint::ast {
|
||||
|
||||
/// A signed int 32 type.
|
||||
class I32 final : public Castable<I32, Type> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
I32(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
I32(I32&&);
|
||||
~I32() override;
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
I32(ProgramID pid, const Source& src);
|
||||
/// Move constructor
|
||||
I32(I32&&);
|
||||
~I32() override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const I32* Clone(CloneContext* ctx) const override;
|
||||
/// Clones this type and all transitive types using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned type
|
||||
const I32* Clone(CloneContext* ctx) const override;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace {
|
||||
using AstI32Test = TestHelper;
|
||||
|
||||
TEST_F(AstI32Test, FriendlyName) {
|
||||
auto* i = create<I32>();
|
||||
EXPECT_EQ(i->FriendlyName(Symbols()), "i32");
|
||||
auto* i = create<I32>();
|
||||
EXPECT_EQ(i->FriendlyName(Symbols()), "i32");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -28,13 +28,13 @@ IdAttribute::IdAttribute(ProgramID pid, const Source& src, uint32_t val)
|
||||
IdAttribute::~IdAttribute() = default;
|
||||
|
||||
std::string IdAttribute::Name() const {
|
||||
return "id";
|
||||
return "id";
|
||||
}
|
||||
|
||||
const IdAttribute* IdAttribute::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<IdAttribute>(src, value);
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<IdAttribute>(src, value);
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user