wgsl: Add support for compound assignment

Implemented in both the reader and writer with E2E tests. Other
backends detect compound assignment and ICE for now.

Bug: tint:1325
Change-Id: Ie3f51e03627a38b12bd1513c4bcf1bebb3282863
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/74363
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
James Price 2022-03-31 22:30:10 +00:00
parent c022ff5b49
commit 555c256344
201 changed files with 2854 additions and 38 deletions

View File

@ -829,10 +829,18 @@ Token Lexer::try_punctuation() {
type = Token::Type::kAndAnd;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "&=")) {
type = Token::Type::kAndEqual;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "&")) {
type = Token::Type::kAnd;
pos_ += 1;
location_.column += 1;
} else if (matches(pos_, "/=")) {
type = Token::Type::kDivisionEqual;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "/")) {
type = Token::Type::kForwardSlash;
pos_ += 1;
@ -885,6 +893,10 @@ Token Lexer::try_punctuation() {
type = Token::Type::kLessThan;
pos_ += 1;
location_.column += 1;
} else if (matches(pos_, "%=")) {
type = Token::Type::kModuloEqual;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "%")) {
type = Token::Type::kMod;
pos_ += 1;
@ -897,6 +909,10 @@ Token Lexer::try_punctuation() {
type = Token::Type::kMinusMinus;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "-=")) {
type = Token::Type::kMinusEqual;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "-")) {
type = Token::Type::kMinus;
pos_ += 1;
@ -909,6 +925,10 @@ Token Lexer::try_punctuation() {
type = Token::Type::kPlusPlus;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "+=")) {
type = Token::Type::kPlusEqual;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "+")) {
type = Token::Type::kPlus;
pos_ += 1;
@ -917,6 +937,10 @@ Token Lexer::try_punctuation() {
type = Token::Type::kOrOr;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "|=")) {
type = Token::Type::kOrEqual;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "|")) {
type = Token::Type::kOr;
pos_ += 1;
@ -925,6 +949,10 @@ Token Lexer::try_punctuation() {
type = Token::Type::kSemicolon;
pos_ += 1;
location_.column += 1;
} else if (matches(pos_, "*=")) {
type = Token::Type::kTimesEqual;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "*")) {
type = Token::Type::kStar;
pos_ += 1;
@ -937,6 +965,10 @@ Token Lexer::try_punctuation() {
type = Token::Type::kUnderscore;
pos_ += 1;
location_.column += 1;
} else if (matches(pos_, "^=")) {
type = Token::Type::kXorEqual;
pos_ += 2;
location_.column += 2;
} else if (matches(pos_, "^")) {
type = Token::Type::kXor;
pos_ += 1;

View File

@ -832,7 +832,15 @@ INSTANTIATE_TEST_SUITE_P(
TokenData{"*", Token::Type::kStar},
TokenData{"~", Token::Type::kTilde},
TokenData{"_", Token::Type::kUnderscore},
TokenData{"^", Token::Type::kXor}));
TokenData{"^", Token::Type::kXor},
TokenData{"+=", Token::Type::kPlusEqual},
TokenData{"-=", Token::Type::kMinusEqual},
TokenData{"*=", Token::Type::kTimesEqual},
TokenData{"/=", Token::Type::kDivisionEqual},
TokenData{"%=", Token::Type::kModuloEqual},
TokenData{"&=", Token::Type::kAndEqual},
TokenData{"|=", Token::Type::kOrEqual},
TokenData{"^=", Token::Type::kXorEqual}));
using KeywordTest = testing::TestWithParam<TokenData>;
TEST_P(KeywordTest, Parses) {

View File

@ -2652,9 +2652,45 @@ Maybe<const ast::Expression*> ParserImpl::logical_or_expression() {
return expect_logical_or_expr(lhs.value);
}
// compound_assignment_operator:
// | plus_equal
// | minus_equal
// | times_equal
// | division_equal
// | modulo_equal
// | and_equal
// | or_equal
// | xor_equal
Maybe<ast::BinaryOp> ParserImpl::compound_assignment_operator() {
ast::BinaryOp compound_op = ast::BinaryOp::kNone;
if (peek_is(Token::Type::kPlusEqual)) {
compound_op = ast::BinaryOp::kAdd;
} else if (peek_is(Token::Type::kMinusEqual)) {
compound_op = ast::BinaryOp::kSubtract;
} else if (peek_is(Token::Type::kTimesEqual)) {
compound_op = ast::BinaryOp::kMultiply;
} else if (peek_is(Token::Type::kDivisionEqual)) {
compound_op = ast::BinaryOp::kDivide;
} else if (peek_is(Token::Type::kModuloEqual)) {
compound_op = ast::BinaryOp::kModulo;
} else if (peek_is(Token::Type::kAndEqual)) {
compound_op = ast::BinaryOp::kAnd;
} else if (peek_is(Token::Type::kOrEqual)) {
compound_op = ast::BinaryOp::kOr;
} else if (peek_is(Token::Type::kXorEqual)) {
compound_op = ast::BinaryOp::kXor;
}
if (compound_op != ast::BinaryOp::kNone) {
next();
return compound_op;
}
return Failure::kNoMatch;
}
// assignment_stmt
// : (unary_expression | underscore) EQUAL logical_or_expression
Maybe<const ast::AssignmentStatement*> ParserImpl::assignment_stmt() {
// | lhs_expression ( equal | compound_assignment_operator ) expression
// | underscore equal expression
Maybe<const ast::Statement*> ParserImpl::assignment_stmt() {
auto t = peek();
auto source = t.source();
@ -2677,9 +2713,15 @@ Maybe<const ast::AssignmentStatement*> ParserImpl::assignment_stmt() {
lhs = create<ast::PhonyExpression>(source);
}
if (!expect("assignment", Token::Type::kEqual)) {
auto compound_op = compound_assignment_operator();
if (compound_op.errored) {
return Failure::kErrored;
}
if (!compound_op.matched) {
if (!expect("assignment", Token::Type::kEqual)) {
return Failure::kErrored;
}
}
auto rhs = logical_or_expression();
if (rhs.errored) {
@ -2689,7 +2731,12 @@ Maybe<const ast::AssignmentStatement*> ParserImpl::assignment_stmt() {
return add_error(peek(), "unable to parse right side of assignment");
}
return create<ast::AssignmentStatement>(source, lhs.value, rhs.value);
if (compound_op.value != ast::BinaryOp::kNone) {
return create<ast::CompoundAssignmentStatement>(
source, lhs.value, rhs.value, compound_op.value);
} else {
return create<ast::AssignmentStatement>(source, lhs.value, rhs.value);
}
}
// const_literal

View File

@ -31,7 +31,6 @@
namespace tint {
namespace ast {
class AssignmentStatement;
class BreakStatement;
class CallStatement;
class ContinueStatement;
@ -657,9 +656,12 @@ class ParserImpl {
/// Parses a `logical_or_expression` grammar element
/// @returns the parsed expression or nullptr
Maybe<const ast::Expression*> logical_or_expression();
/// Parses a `compound_assignment_operator` grammar element
/// @returns the parsed compound assignment operator
Maybe<ast::BinaryOp> compound_assignment_operator();
/// Parses a `assignment_stmt` grammar element
/// @returns the parsed assignment or nullptr
Maybe<const ast::AssignmentStatement*> assignment_stmt();
Maybe<const ast::Statement*> assignment_stmt();
/// Parses one or more attribute lists.
/// @return the parsed attribute list, or an empty list on error.
Maybe<ast::AttributeList> attribute_list();

View File

@ -27,17 +27,17 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
ASSERT_NE(e->lhs, nullptr);
ASSERT_NE(e->rhs, nullptr);
auto* a = e->As<ast::AssignmentStatement>();
ASSERT_NE(a, nullptr);
ASSERT_NE(a->lhs, nullptr);
ASSERT_NE(a->rhs, nullptr);
ASSERT_TRUE(e->lhs->Is<ast::IdentifierExpression>());
auto* ident = e->lhs->As<ast::IdentifierExpression>();
ASSERT_TRUE(a->lhs->Is<ast::IdentifierExpression>());
auto* ident = a->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_NE(e->rhs, nullptr);
ASSERT_TRUE(e->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(e->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(a->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::SintLiteralExpression>()->value, 123);
}
TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
@ -48,16 +48,16 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
ASSERT_NE(e->lhs, nullptr);
ASSERT_NE(e->rhs, nullptr);
auto* a = e->As<ast::AssignmentStatement>();
ASSERT_NE(a, nullptr);
ASSERT_NE(a->lhs, nullptr);
ASSERT_NE(a->rhs, nullptr);
ASSERT_NE(e->rhs, nullptr);
ASSERT_TRUE(e->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(e->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(a->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(e->lhs->Is<ast::MemberAccessorExpression>());
auto* mem = e->lhs->As<ast::MemberAccessorExpression>();
ASSERT_TRUE(a->lhs->Is<ast::MemberAccessorExpression>());
auto* mem = a->lhs->As<ast::MemberAccessorExpression>();
ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
auto* ident = mem->member->As<ast::IdentifierExpression>();
@ -96,15 +96,37 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToPhony) {
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
ASSERT_NE(e->lhs, nullptr);
ASSERT_NE(e->rhs, nullptr);
auto* a = e->As<ast::AssignmentStatement>();
ASSERT_NE(a, nullptr);
ASSERT_NE(a->lhs, nullptr);
ASSERT_NE(a->rhs, nullptr);
ASSERT_NE(e->rhs, nullptr);
ASSERT_TRUE(e->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(e->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(a->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::SintLiteralExpression>()->value, 123);
ASSERT_TRUE(e->lhs->Is<ast::PhonyExpression>());
ASSERT_TRUE(a->lhs->Is<ast::PhonyExpression>());
}
TEST_F(ParserImplTest, AssignmentStmt_Parses_CompoundOp) {
auto p = parser("a += 123");
auto e = p->assignment_stmt();
EXPECT_TRUE(e.matched);
EXPECT_FALSE(e.errored);
EXPECT_FALSE(p->has_error()) << p->error();
ASSERT_NE(e.value, nullptr);
auto* a = e->As<ast::CompoundAssignmentStatement>();
ASSERT_NE(a, nullptr);
ASSERT_NE(a->lhs, nullptr);
ASSERT_NE(a->rhs, nullptr);
EXPECT_EQ(a->op, ast::BinaryOp::kAdd);
ASSERT_TRUE(a->lhs->Is<ast::IdentifierExpression>());
auto* ident = a->lhs->As<ast::IdentifierExpression>();
EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
ASSERT_TRUE(a->rhs->Is<ast::SintLiteralExpression>());
EXPECT_EQ(a->rhs->As<ast::SintLiteralExpression>()->value, 123);
}
TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {
@ -117,6 +139,16 @@ TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {
EXPECT_EQ(p->error(), "1:12: expected '=' for assignment");
}
TEST_F(ParserImplTest, AssignmentStmt_Compound_MissingEqual) {
auto p = parser("a + 123");
auto e = p->assignment_stmt();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(e.value, nullptr);
EXPECT_EQ(p->error(), "1:3: expected '=' for assignment");
}
TEST_F(ParserImplTest, AssignmentStmt_InvalidLHS) {
auto p = parser("if (true) {} = 123");
auto e = p->assignment_stmt();
@ -136,6 +168,16 @@ TEST_F(ParserImplTest, AssignmentStmt_InvalidRHS) {
EXPECT_EQ(p->error(), "1:14: unable to parse right side of assignment");
}
TEST_F(ParserImplTest, AssignmentStmt_InvalidCompoundOp) {
auto p = parser("a &&= true");
auto e = p->assignment_stmt();
EXPECT_FALSE(e.matched);
EXPECT_TRUE(e.errored);
EXPECT_EQ(e.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:3: expected '=' for assignment");
}
} // namespace
} // namespace wgsl
} // namespace reader

View File

@ -108,6 +108,22 @@ std::string_view Token::TypeToName(Type type) {
return "_";
case Token::Type::kXor:
return "^";
case Token::Type::kPlusEqual:
return "+=";
case Token::Type::kMinusEqual:
return "-=";
case Token::Type::kTimesEqual:
return "*=";
case Token::Type::kDivisionEqual:
return "/=";
case Token::Type::kModuloEqual:
return "%=";
case Token::Type::kAndEqual:
return "&=";
case Token::Type::kOrEqual:
return "|=";
case Token::Type::kXorEqual:
return "^=";
case Token::Type::kArray:
return "array";

View File

@ -118,6 +118,22 @@ class Token {
kUnderscore,
/// A '^'
kXor,
/// A '+='
kPlusEqual,
/// A '-='
kMinusEqual,
/// A '*='
kTimesEqual,
/// A '/='
kDivisionEqual,
/// A '%='
kModuloEqual,
/// A '&='
kAndEqual,
/// A '|='
kOrEqual,
/// A '^='
kXorEqual,
/// A 'array'
kArray,

View File

@ -786,8 +786,21 @@ bool GeneratorImpl::EmitBinary(std::ostream& out,
return false;
}
out << " ";
if (!EmitBinaryOp(out, expr->op)) {
return false;
}
out << " ";
switch (expr->op) {
if (!EmitExpression(out, expr->rhs)) {
return false;
}
out << ")";
return true;
}
bool GeneratorImpl::EmitBinaryOp(std::ostream& out, const ast::BinaryOp op) {
switch (op) {
case ast::BinaryOp::kAnd:
out << "&";
break;
@ -847,13 +860,6 @@ bool GeneratorImpl::EmitBinary(std::ostream& out,
"missing binary operation type");
return false;
}
out << " ";
if (!EmitExpression(out, expr->rhs)) {
return false;
}
out << ")";
return true;
}
@ -911,6 +917,9 @@ bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
out << ";";
return true;
},
[&](const ast::CompoundAssignmentStatement* c) {
return EmitCompoundAssign(c);
},
[&](const ast::ContinueStatement* c) { return EmitContinue(c); },
[&](const ast::DiscardStatement* d) { return EmitDiscard(d); },
[&](const ast::FallthroughStatement* f) { return EmitFallthrough(f); },
@ -996,6 +1005,29 @@ bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
return true;
}
bool GeneratorImpl::EmitCompoundAssign(
const ast::CompoundAssignmentStatement* stmt) {
auto out = line();
if (!EmitExpression(out, stmt->lhs)) {
return false;
}
out << " ";
if (!EmitBinaryOp(out, stmt->op)) {
return false;
}
out << "= ";
if (!EmitExpression(out, stmt->rhs)) {
return false;
}
out << ";";
return true;
}
bool GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
line() << "continue;";
return true;

View File

@ -21,6 +21,7 @@
#include "src/tint/ast/binary_expression.h"
#include "src/tint/ast/bitcast_expression.h"
#include "src/tint/ast/break_statement.h"
#include "src/tint/ast/compound_assignment_statement.h"
#include "src/tint/ast/continue_statement.h"
#include "src/tint/ast/discard_statement.h"
#include "src/tint/ast/fallthrough_statement.h"
@ -72,6 +73,11 @@ class GeneratorImpl : public TextGenerator {
/// @param expr the binary expression
/// @returns true if the expression was emitted, false otherwise
bool EmitBinary(std::ostream& out, const ast::BinaryExpression* expr);
/// Handles generating a binary operator
/// @param out the output of the expression stream
/// @param op the binary operator
/// @returns true if the operator was emitted, false otherwise
bool EmitBinaryOp(std::ostream& out, const ast::BinaryOp op);
/// Handles generating a bitcast expression
/// @param out the output of the expression stream
/// @param expr the bitcast expression
@ -94,6 +100,10 @@ class GeneratorImpl : public TextGenerator {
/// @param stmt the statement
/// @returns true if the statment was emitted successfully
bool EmitCase(const ast::CaseStatement* stmt);
/// Handles a compound assignment statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt);
/// Handles generating a literal expression
/// @param out the output of the expression stream
/// @param expr the literal expression expression

View File

@ -0,0 +1,20 @@
struct S {
a : array<vec4<i32>, 4>,
}
var<private> counter : i32;
fn foo() -> i32 {
counter += 1;
return counter;
}
fn bar() -> i32 {
counter += 2;
return counter;
}
fn main() {
var x = S();
let p = &x;
// foo() and bar() should only be called once each.
(*p).a[foo()][bar()] += 5;
}

View File

@ -0,0 +1,26 @@
SKIP: FAILED
struct S {
a : array<vec4<i32>, 4>,
}
var<private> counter : i32;
fn foo() -> i32 {
counter += 1;
return counter;
}
fn bar() -> i32 {
counter += 2;
return counter;
}
fn main() {
var x = S();
let p = &(x);
(*(p)).a[foo()][bar()] += 5;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,26 @@
SKIP: FAILED
struct S {
a : array<vec4<i32>, 4>,
}
var<private> counter : i32;
fn foo() -> i32 {
counter += 1;
return counter;
}
fn bar() -> i32 {
counter += 2;
return counter;
}
fn main() {
var x = S();
let p = &(x);
(*(p)).a[foo()][bar()] += 5;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,26 @@
SKIP: FAILED
struct S {
a : array<vec4<i32>, 4>,
}
var<private> counter : i32;
fn foo() -> i32 {
counter += 1;
return counter;
}
fn bar() -> i32 {
counter += 2;
return counter;
}
fn tint_symbol() {
var x = S();
let p = &(x);
(*(p)).a[foo()][bar()] += 5;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,26 @@
SKIP: FAILED
struct S {
a : array<vec4<i32>, 4>,
}
var<private> counter : i32;
fn foo() -> i32 {
counter += 1;
return counter;
}
fn bar() -> i32 {
counter += 2;
return counter;
}
fn main() {
var x = S();
let p = &(x);
(*(p)).a[foo()][bar()] += 5;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,21 @@
struct S {
a : array<vec4<i32>, 4>,
}
var<private> counter : i32;
fn foo() -> i32 {
counter += 1;
return counter;
}
fn bar() -> i32 {
counter += 2;
return counter;
}
fn main() {
var x = S();
let p = &(x);
(*(p)).a[foo()][bar()] += 5;
}

View File

@ -0,0 +1,14 @@
var<private> a : i32;
var<private> b : f32;
fn foo(maybe_zero : i32) {
a /= 0;
a %= 0;
a /= maybe_zero;
a %= maybe_zero;
b /= 0.0;
b %= 0.0;
b /= f32(maybe_zero);
b %= f32(maybe_zero);
}

View File

@ -0,0 +1,19 @@
SKIP: FAILED
var<private> a : i32;
var<private> b : f32;
fn foo(maybe_zero : i32) {
a /= 0;
a %= 0;
a /= maybe_zero;
a %= maybe_zero;
b /= 0.0;
b %= 0.0;
b /= f32(maybe_zero);
b %= f32(maybe_zero);
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,19 @@
SKIP: FAILED
var<private> a : i32;
var<private> b : f32;
fn foo(maybe_zero : i32) {
a /= 0;
a %= 0;
a /= maybe_zero;
a %= maybe_zero;
b /= 0.0;
b %= 0.0;
b /= f32(maybe_zero);
b %= f32(maybe_zero);
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,19 @@
SKIP: FAILED
var<private> a : i32;
var<private> b : f32;
fn foo(maybe_zero : i32) {
a /= 0;
a %= 0;
a /= maybe_zero;
a %= maybe_zero;
b /= 0.0;
b %= 0.0;
b /= f32(maybe_zero);
b %= f32(maybe_zero);
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,19 @@
SKIP: FAILED
var<private> a : i32;
var<private> b : f32;
fn foo(maybe_zero : i32) {
a /= 0;
a %= 0;
a /= maybe_zero;
a %= maybe_zero;
b /= 0.0;
b %= 0.0;
b /= f32(maybe_zero);
b %= f32(maybe_zero);
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
var<private> a : i32;
var<private> b : f32;
fn foo(maybe_zero : i32) {
a /= 0;
a %= 0;
a /= maybe_zero;
a %= maybe_zero;
b /= 0.0;
b %= 0.0;
b /= f32(maybe_zero);
b %= f32(maybe_zero);
}

View File

@ -0,0 +1,31 @@
struct S {
a : i32,
b : vec4<f32>,
c : mat2x2<f32>,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
var<private> i : u32;
fn idx1() -> i32 {
i += 1u;
return 1;
}
fn idx2() -> i32 {
i += 2u;
return 1;
}
fn idx3() -> i32 {
i += 3u;
return 1;
}
fn foo() {
var a = array<f32, 4>();
// Make sure that the functions are only evaluated once each.
for (a[idx1()] *= 2.0; a[idx2()] < 10.0; a[idx3()] += 1.0) {
}
}

View File

@ -0,0 +1,35 @@
SKIP: FAILED
struct S {
a : i32,
b : vec4<f32>,
c : mat2x2<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
var<private> i : u32;
fn idx1() -> i32 {
i += 1u;
return 1;
}
fn idx2() -> i32 {
i += 2u;
return 1;
}
fn idx3() -> i32 {
i += 3u;
return 1;
}
fn foo() {
var a = array<f32, 4>();
for(a[idx1()] *= 2.0; (a[idx2()] < 10.0); a[idx3()] += 1.0) {
}
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,35 @@
SKIP: FAILED
struct S {
a : i32,
b : vec4<f32>,
c : mat2x2<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
var<private> i : u32;
fn idx1() -> i32 {
i += 1u;
return 1;
}
fn idx2() -> i32 {
i += 2u;
return 1;
}
fn idx3() -> i32 {
i += 3u;
return 1;
}
fn foo() {
var a = array<f32, 4>();
for(a[idx1()] *= 2.0; (a[idx2()] < 10.0); a[idx3()] += 1.0) {
}
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,35 @@
SKIP: FAILED
struct S {
a : i32,
b : vec4<f32>,
c : mat2x2<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
var<private> i : u32;
fn idx1() -> i32 {
i += 1u;
return 1;
}
fn idx2() -> i32 {
i += 2u;
return 1;
}
fn idx3() -> i32 {
i += 3u;
return 1;
}
fn foo() {
var a = array<f32, 4>();
for(a[idx1()] *= 2.0; (a[idx2()] < 10.0); a[idx3()] += 1.0) {
}
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,35 @@
SKIP: FAILED
struct S {
a : i32,
b : vec4<f32>,
c : mat2x2<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
var<private> i : u32;
fn idx1() -> i32 {
i += 1u;
return 1;
}
fn idx2() -> i32 {
i += 2u;
return 1;
}
fn idx3() -> i32 {
i += 3u;
return 1;
}
fn foo() {
var a = array<f32, 4>();
for(a[idx1()] *= 2.0; (a[idx2()] < 10.0); a[idx3()] += 1.0) {
}
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,30 @@
struct S {
a : i32,
b : vec4<f32>,
c : mat2x2<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
var<private> i : u32;
fn idx1() -> i32 {
i += 1u;
return 1;
}
fn idx2() -> i32 {
i += 2u;
return 1;
}
fn idx3() -> i32 {
i += 3u;
return 1;
}
fn foo() {
var a = array<f32, 4>();
for(a[idx1()] *= 2.0; (a[idx2()] < 10.0); a[idx3()] += 1.0) {
}
}

View File

@ -0,0 +1,9 @@
fn foo() {
var<function> a : i32;
var<function> b : vec4<f32>;
var<function> c : mat2x2<f32>;
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}

View File

@ -0,0 +1,13 @@
SKIP: FAILED
fn foo() {
var<function> a : i32;
var<function> b : vec4<f32>;
var<function> c : mat2x2<f32>;
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,13 @@
SKIP: FAILED
fn foo() {
var<function> a : i32;
var<function> b : vec4<f32>;
var<function> c : mat2x2<f32>;
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,13 @@
SKIP: FAILED
fn foo() {
var<function> a : i32;
var<function> b : vec4<f32>;
var<function> c : mat2x2<f32>;
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,13 @@
SKIP: FAILED
fn foo() {
var<function> a : i32;
var<function> b : vec4<f32>;
var<function> c : mat2x2<f32>;
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,8 @@
fn foo() {
var<function> a : i32;
var<function> b : vec4<f32>;
var<function> c : mat2x2<f32>;
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}

View File

@ -0,0 +1,9 @@
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a -= mat4x4<f32>();
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= mat4x4<f32>();
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= mat4x4<f32>();
}
Failed to generate: error: cannot assign to value of type 'mat4x4<f32>'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= mat4x4<f32>();
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= mat4x4<f32>();
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= mat4x4<f32>();
}

View File

@ -0,0 +1,9 @@
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a += mat4x4<f32>();
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += mat4x4<f32>();
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += mat4x4<f32>();
}
Failed to generate: error: cannot assign to value of type 'mat4x4<f32>'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += mat4x4<f32>();
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += mat4x4<f32>();
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += mat4x4<f32>();
}

View File

@ -0,0 +1,9 @@
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a *= 2.0;
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= 2.0;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= 2.0;
}
Failed to generate: error: cannot assign to value of type 'mat4x4<f32>'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= 2.0;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= 2.0;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= 2.0;
}

View File

@ -0,0 +1,9 @@
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a *= mat4x4<f32>();
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= mat4x4<f32>();
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= mat4x4<f32>();
}
Failed to generate: error: cannot assign to value of type 'mat4x4<f32>'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= mat4x4<f32>();
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= mat4x4<f32>();
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : mat4x4<f32>,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a *= mat4x4<f32>();
}

View File

@ -0,0 +1,9 @@
var<private> a : i32;
var<private> b : vec4<f32>;
var<private> c : mat2x2<f32>;
fn foo() {
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}

View File

@ -0,0 +1,16 @@
SKIP: FAILED
var<private> a : i32;
var<private> b : vec4<f32>;
var<private> c : mat2x2<f32>;
fn foo() {
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,16 @@
SKIP: FAILED
var<private> a : i32;
var<private> b : vec4<f32>;
var<private> c : mat2x2<f32>;
fn foo() {
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,16 @@
SKIP: FAILED
var<private> a : i32;
var<private> b : vec4<f32>;
var<private> c : mat2x2<f32>;
fn foo() {
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,16 @@
SKIP: FAILED
var<private> a : i32;
var<private> b : vec4<f32>;
var<private> c : mat2x2<f32>;
fn foo() {
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,11 @@
var<private> a : i32;
var<private> b : vec4<f32>;
var<private> c : mat2x2<f32>;
fn foo() {
a /= 2;
b *= mat4x4<f32>();
c *= 2.0;
}

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a &= 2;
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a &= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a &= 2;
}
Failed to generate: error: cannot assign to value of type 'i32'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a &= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a &= 2;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a &= 2;
}

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a /= 2;
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a /= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a /= 2;
}
Failed to generate: error: cannot assign to value of type 'i32'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a /= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a /= 2;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a /= 2;
}

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a -= 2;
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= 2;
}
Failed to generate: error: cannot assign to value of type 'i32'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= 2;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a -= 2;
}

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a %= 2;
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a %= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a %= 2;
}
Failed to generate: error: cannot assign to value of type 'i32'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a %= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a %= 2;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a %= 2;
}

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a |= 2;
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a |= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a |= 2;
}
Failed to generate: error: cannot assign to value of type 'i32'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a |= 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a |= 2;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a |= 2;
}

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a += 2;
}

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += 2;
}
Failed to generate: error: cannot assign to value of type 'i32'

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += 2;
}
Failed to generate: error: unknown statement type: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,14 @@
SKIP: FAILED
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += 2;
}
Failed to generate: Unknown statement: tint::ast::CompoundAssignmentStatement

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0) var<storage, read_write> v : S;
fn foo() {
v.a += 2;
}

View File

@ -0,0 +1,9 @@
struct S {
a : i32,
}
@group(0) @binding(0)
var<storage, read_write> v : S;
fn foo() {
v.a *= 2;
}

Some files were not shown because too many files have changed in this diff Show More