mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-06 22:53:35 +00:00
Transforms a for-loop into a loop. Will be required by the SPIR-V writer. Bug: tint:952 Change-Id: Iba859bd144d702cee85374f2cfcb94cd7465ca98 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/57202 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: James Price <jrprice@google.com>
342 lines
4.9 KiB
C++
342 lines
4.9 KiB
C++
// Copyright 2021 The Tint Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "src/transform/for_loop_to_loop.h"
|
|
|
|
#include "src/transform/test_helper.h"
|
|
|
|
namespace tint {
|
|
namespace transform {
|
|
namespace {
|
|
|
|
using ForLoopToLoopTest = TransformTest;
|
|
|
|
TEST_F(ForLoopToLoopTest, EmptyModule) {
|
|
auto* src = "";
|
|
auto* expect = src;
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test an empty for loop.
|
|
TEST_F(ForLoopToLoopTest, Empty) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
for (;;) {
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
loop {
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop with non-empty body.
|
|
TEST_F(ForLoopToLoopTest, Body) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
for (;;) {
|
|
discard;
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
loop {
|
|
discard;
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop declaring a variable in the initializer statement.
|
|
TEST_F(ForLoopToLoopTest, InitializerStatementDecl) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
for (var i: i32;;) {
|
|
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
{
|
|
var i : i32;
|
|
loop {
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop declaring and initializing a variable in the initializer
|
|
// statement.
|
|
TEST_F(ForLoopToLoopTest, InitializerStatementDeclEqual) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
for (var i: i32 = 0;;) {
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
{
|
|
var i : i32 = 0;
|
|
loop {
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop declaring a const variable in the initializer statement.
|
|
TEST_F(ForLoopToLoopTest, InitializerStatementConstDecl) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
for (let i: i32 = 0;;) {
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
{
|
|
let i : i32 = 0;
|
|
loop {
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop assigning a variable in the initializer statement.
|
|
TEST_F(ForLoopToLoopTest, InitializerStatementAssignment) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
var i: i32;
|
|
for (i = 0;;) {
|
|
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
var i : i32;
|
|
{
|
|
i = 0;
|
|
loop {
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop calling a function in the initializer statement.
|
|
TEST_F(ForLoopToLoopTest, InitializerStatementFuncCall) {
|
|
auto* src = R"(
|
|
fn a(x : i32, y : i32) {
|
|
}
|
|
|
|
fn f() {
|
|
var b : i32;
|
|
var c : i32;
|
|
for (a(b,c);;) { }
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn a(x : i32, y : i32) {
|
|
}
|
|
|
|
fn f() {
|
|
var b : i32;
|
|
var c : i32;
|
|
{
|
|
a(b, c);
|
|
loop {
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop with a break condition
|
|
TEST_F(ForLoopToLoopTest, BreakCondition) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
for (; 0 == 1;) {
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
loop {
|
|
if (!((0 == 1))) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop assigning a variable in the continuing statement.
|
|
TEST_F(ForLoopToLoopTest, ContinuingAssignment) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
var x: i32;
|
|
for (;;x = 2) {
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
var x : i32;
|
|
loop {
|
|
|
|
continuing {
|
|
x = 2;
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop calling a function in the continuing statement.
|
|
TEST_F(ForLoopToLoopTest, ContinuingFuncCall) {
|
|
auto* src = R"(
|
|
fn a(x : i32, y : i32) {
|
|
}
|
|
|
|
fn f() {
|
|
var b : i32;
|
|
var c : i32;
|
|
for (;;a(b,c)) {
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn a(x : i32, y : i32) {
|
|
}
|
|
|
|
fn f() {
|
|
var b : i32;
|
|
var c : i32;
|
|
loop {
|
|
|
|
continuing {
|
|
a(b, c);
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
// Test a for loop with all statements non-empty.
|
|
TEST_F(ForLoopToLoopTest, All) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
var a : i32;
|
|
for(var i : i32 = 0; i < 4; i = i + 1) {
|
|
if (a == 0) {
|
|
continue;
|
|
}
|
|
a = a + 2;
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
var a : i32;
|
|
{
|
|
var i : i32 = 0;
|
|
loop {
|
|
if (!((i < 4))) {
|
|
break;
|
|
}
|
|
if ((a == 0)) {
|
|
continue;
|
|
}
|
|
a = (a + 2);
|
|
|
|
continuing {
|
|
i = (i + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<ForLoopToLoop>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace transform
|
|
} // namespace tint
|