[tint][ir] Clean up tests
Remove the direct use of BuilderImpl from TestHelperBase to cut down the amount of internal state management required by the tests, and removing confusing conflation between the BuilderImpl and Builder. This change removes the following methods from TestHelperBase: * CreateBuilder() * InjectFlowBlock() * CreateEmptyBuilder() * FlowNodeForAstNode() Tests now just use FromProgram() function for testing AST -> IR. The downside to the black-box testing is that the per-method granularity of the unit testing increases to whole FromProgram() granularity. However, my personal opinion is that this is more than offset by the lack of state leakage from the implementation to the tests. Bug tint:1718 Change-Id: Iba2560e0fbcbd3dfb936694e50997d716f09fbd8 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/132960 Kokoro: Ben Clayton <bclayton@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
0aa34f27b2
commit
36aa48ce36
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/tint/ir/builder.h"
|
||||||
#include "src/tint/ir/instruction.h"
|
#include "src/tint/ir/instruction.h"
|
||||||
#include "src/tint/ir/test_helper.h"
|
#include "src/tint/ir/test_helper.h"
|
||||||
|
|
||||||
|
@ -23,10 +24,9 @@ using namespace tint::number_suffixes; // NOLINT
|
||||||
using IR_InstructionTest = TestHelper;
|
using IR_InstructionTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateAnd) {
|
TEST_F(IR_InstructionTest, CreateAnd) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.And(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
|
const auto* inst = b.And(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
|
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
|
||||||
|
@ -45,10 +45,9 @@ TEST_F(IR_InstructionTest, CreateAnd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateOr) {
|
TEST_F(IR_InstructionTest, CreateOr) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Or(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
|
const auto* inst = b.Or(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kOr);
|
EXPECT_EQ(inst->kind, Binary::Kind::kOr);
|
||||||
|
@ -65,10 +64,9 @@ TEST_F(IR_InstructionTest, CreateOr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateXor) {
|
TEST_F(IR_InstructionTest, CreateXor) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Xor(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
|
const auto* inst = b.Xor(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kXor);
|
EXPECT_EQ(inst->kind, Binary::Kind::kXor);
|
||||||
|
@ -85,10 +83,9 @@ TEST_F(IR_InstructionTest, CreateXor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateEqual) {
|
TEST_F(IR_InstructionTest, CreateEqual) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Equal(b.builder.ir.types.Get<type::Bool>(),
|
const auto* inst = b.Equal(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kEqual);
|
EXPECT_EQ(inst->kind, Binary::Kind::kEqual);
|
||||||
|
@ -105,10 +102,9 @@ TEST_F(IR_InstructionTest, CreateEqual) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateNotEqual) {
|
TEST_F(IR_InstructionTest, CreateNotEqual) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.NotEqual(b.builder.ir.types.Get<type::Bool>(),
|
const auto* inst = b.NotEqual(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kNotEqual);
|
EXPECT_EQ(inst->kind, Binary::Kind::kNotEqual);
|
||||||
|
@ -125,10 +121,9 @@ TEST_F(IR_InstructionTest, CreateNotEqual) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateLessThan) {
|
TEST_F(IR_InstructionTest, CreateLessThan) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.LessThan(b.builder.ir.types.Get<type::Bool>(),
|
const auto* inst = b.LessThan(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kLessThan);
|
EXPECT_EQ(inst->kind, Binary::Kind::kLessThan);
|
||||||
|
@ -145,10 +140,10 @@ TEST_F(IR_InstructionTest, CreateLessThan) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateGreaterThan) {
|
TEST_F(IR_InstructionTest, CreateGreaterThan) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.GreaterThan(b.builder.ir.types.Get<type::Bool>(),
|
const auto* inst =
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
b.GreaterThan(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kGreaterThan);
|
EXPECT_EQ(inst->kind, Binary::Kind::kGreaterThan);
|
||||||
|
@ -165,10 +160,10 @@ TEST_F(IR_InstructionTest, CreateGreaterThan) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateLessThanEqual) {
|
TEST_F(IR_InstructionTest, CreateLessThanEqual) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.LessThanEqual(b.builder.ir.types.Get<type::Bool>(),
|
const auto* inst =
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
b.LessThanEqual(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kLessThanEqual);
|
EXPECT_EQ(inst->kind, Binary::Kind::kLessThanEqual);
|
||||||
|
@ -185,10 +180,10 @@ TEST_F(IR_InstructionTest, CreateLessThanEqual) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateGreaterThanEqual) {
|
TEST_F(IR_InstructionTest, CreateGreaterThanEqual) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.GreaterThanEqual(b.builder.ir.types.Get<type::Bool>(),
|
const auto* inst =
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
b.GreaterThanEqual(b.ir.types.Get<type::Bool>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kGreaterThanEqual);
|
EXPECT_EQ(inst->kind, Binary::Kind::kGreaterThanEqual);
|
||||||
|
@ -205,9 +200,8 @@ TEST_F(IR_InstructionTest, CreateGreaterThanEqual) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateNot) {
|
TEST_F(IR_InstructionTest, CreateNot) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
const auto* inst =
|
const auto* inst = b.Not(b.ir.types.Get<type::Bool>(), b.Constant(true));
|
||||||
b.builder.Not(b.builder.ir.types.Get<type::Bool>(), b.builder.Constant(true));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kEqual);
|
EXPECT_EQ(inst->kind, Binary::Kind::kEqual);
|
||||||
|
@ -224,10 +218,9 @@ TEST_F(IR_InstructionTest, CreateNot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateShiftLeft) {
|
TEST_F(IR_InstructionTest, CreateShiftLeft) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.ShiftLeft(b.builder.ir.types.Get<type::I32>(),
|
const auto* inst = b.ShiftLeft(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kShiftLeft);
|
EXPECT_EQ(inst->kind, Binary::Kind::kShiftLeft);
|
||||||
|
@ -244,10 +237,9 @@ TEST_F(IR_InstructionTest, CreateShiftLeft) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateShiftRight) {
|
TEST_F(IR_InstructionTest, CreateShiftRight) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.ShiftRight(b.builder.ir.types.Get<type::I32>(),
|
const auto* inst = b.ShiftRight(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kShiftRight);
|
EXPECT_EQ(inst->kind, Binary::Kind::kShiftRight);
|
||||||
|
@ -264,10 +256,9 @@ TEST_F(IR_InstructionTest, CreateShiftRight) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateAdd) {
|
TEST_F(IR_InstructionTest, CreateAdd) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Add(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
|
const auto* inst = b.Add(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kAdd);
|
EXPECT_EQ(inst->kind, Binary::Kind::kAdd);
|
||||||
|
@ -284,10 +275,9 @@ TEST_F(IR_InstructionTest, CreateAdd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateSubtract) {
|
TEST_F(IR_InstructionTest, CreateSubtract) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Subtract(b.builder.ir.types.Get<type::I32>(),
|
const auto* inst = b.Subtract(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kSubtract);
|
EXPECT_EQ(inst->kind, Binary::Kind::kSubtract);
|
||||||
|
@ -304,10 +294,9 @@ TEST_F(IR_InstructionTest, CreateSubtract) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateMultiply) {
|
TEST_F(IR_InstructionTest, CreateMultiply) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Multiply(b.builder.ir.types.Get<type::I32>(),
|
const auto* inst = b.Multiply(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kMultiply);
|
EXPECT_EQ(inst->kind, Binary::Kind::kMultiply);
|
||||||
|
@ -324,10 +313,9 @@ TEST_F(IR_InstructionTest, CreateMultiply) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateDivide) {
|
TEST_F(IR_InstructionTest, CreateDivide) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Divide(b.builder.ir.types.Get<type::I32>(),
|
const auto* inst = b.Divide(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kDivide);
|
EXPECT_EQ(inst->kind, Binary::Kind::kDivide);
|
||||||
|
@ -344,10 +332,9 @@ TEST_F(IR_InstructionTest, CreateDivide) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateModulo) {
|
TEST_F(IR_InstructionTest, CreateModulo) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Modulo(b.builder.ir.types.Get<type::I32>(),
|
const auto* inst = b.Modulo(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(4_i), b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Binary>());
|
ASSERT_TRUE(inst->Is<Binary>());
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kModulo);
|
EXPECT_EQ(inst->kind, Binary::Kind::kModulo);
|
||||||
|
@ -364,9 +351,8 @@ TEST_F(IR_InstructionTest, CreateModulo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, Binary_Usage) {
|
TEST_F(IR_InstructionTest, Binary_Usage) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
const auto* inst = b.builder.And(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i),
|
const auto* inst = b.And(b.ir.types.Get<type::I32>(), b.Constant(4_i), b.Constant(2_i));
|
||||||
b.builder.Constant(2_i));
|
|
||||||
|
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
|
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
|
||||||
|
|
||||||
|
@ -380,9 +366,9 @@ TEST_F(IR_InstructionTest, Binary_Usage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, Binary_Usage_DuplicateValue) {
|
TEST_F(IR_InstructionTest, Binary_Usage_DuplicateValue) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
auto val = b.builder.Constant(4_i);
|
auto val = b.Constant(4_i);
|
||||||
const auto* inst = b.builder.And(b.builder.ir.types.Get<type::I32>(), val, val);
|
const auto* inst = b.And(b.ir.types.Get<type::I32>(), val, val);
|
||||||
|
|
||||||
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
|
EXPECT_EQ(inst->kind, Binary::Kind::kAnd);
|
||||||
ASSERT_EQ(inst->LHS(), inst->RHS());
|
ASSERT_EQ(inst->LHS(), inst->RHS());
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/tint/ir/builder.h"
|
||||||
|
#include "src/tint/ir/constant.h"
|
||||||
#include "src/tint/ir/instruction.h"
|
#include "src/tint/ir/instruction.h"
|
||||||
#include "src/tint/ir/test_helper.h"
|
#include "src/tint/ir/test_helper.h"
|
||||||
|
|
||||||
|
@ -23,9 +25,8 @@ using namespace tint::number_suffixes; // NOLINT
|
||||||
using IR_InstructionTest = TestHelper;
|
using IR_InstructionTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, Bitcast) {
|
TEST_F(IR_InstructionTest, Bitcast) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
const auto* inst =
|
const auto* inst = b.Bitcast(b.ir.types.Get<type::I32>(), b.Constant(4_i));
|
||||||
b.builder.Bitcast(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<ir::Bitcast>());
|
ASSERT_TRUE(inst->Is<ir::Bitcast>());
|
||||||
ASSERT_NE(inst->Type(), nullptr);
|
ASSERT_NE(inst->Type(), nullptr);
|
||||||
|
@ -38,9 +39,8 @@ TEST_F(IR_InstructionTest, Bitcast) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, Bitcast_Usage) {
|
TEST_F(IR_InstructionTest, Bitcast_Usage) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
const auto* inst =
|
const auto* inst = b.Bitcast(b.ir.types.Get<type::I32>(), b.Constant(4_i));
|
||||||
b.builder.Bitcast(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
|
|
||||||
|
|
||||||
ASSERT_EQ(inst->args.Length(), 1u);
|
ASSERT_EQ(inst->args.Length(), 1u);
|
||||||
ASSERT_NE(inst->args[0], nullptr);
|
ASSERT_NE(inst->args[0], nullptr);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "src/tint/ast/const_assert.h"
|
#include "src/tint/ast/const_assert.h"
|
||||||
#include "src/tint/ast/continue_statement.h"
|
#include "src/tint/ast/continue_statement.h"
|
||||||
#include "src/tint/ast/discard_statement.h"
|
#include "src/tint/ast/discard_statement.h"
|
||||||
|
#include "src/tint/ast/enable.h"
|
||||||
#include "src/tint/ast/float_literal_expression.h"
|
#include "src/tint/ast/float_literal_expression.h"
|
||||||
#include "src/tint/ast/for_loop_statement.h"
|
#include "src/tint/ast/for_loop_statement.h"
|
||||||
#include "src/tint/ast/function.h"
|
#include "src/tint/ast/function.h"
|
||||||
|
@ -182,10 +183,10 @@ ResultType BuilderImpl::Build() {
|
||||||
EmitVariable(var);
|
EmitVariable(var);
|
||||||
},
|
},
|
||||||
[&](const ast::Function* func) { EmitFunction(func); },
|
[&](const ast::Function* func) { EmitFunction(func); },
|
||||||
// [&](const ast::Enable*) {
|
[&](const ast::Enable*) {
|
||||||
// TODO(dsinclair): Implement? I think these need to be passed along so further stages
|
// TODO(dsinclair): Implement? I think these need to be passed along so further
|
||||||
// know what is enabled.
|
// stages know what is enabled.
|
||||||
// },
|
},
|
||||||
[&](const ast::ConstAssert*) {
|
[&](const ast::ConstAssert*) {
|
||||||
// Evaluated by the resolver, drop from the IR.
|
// Evaluated by the resolver, drop from the IR.
|
||||||
},
|
},
|
||||||
|
|
|
@ -31,16 +31,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) {
|
||||||
auto* expr = Add(Call("my_func"), 4_u);
|
auto* expr = Add(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = add %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = add %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,11 +54,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundAdd) {
|
||||||
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kAdd);
|
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kAdd);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, u32, read_write> = var private, read_write
|
%v1:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,16 +77,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) {
|
||||||
auto* expr = Sub(Call("my_func"), 4_u);
|
auto* expr = Sub(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = sub %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = sub %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,11 +100,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundSubtract) {
|
||||||
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kSubtract);
|
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kSubtract);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, u32, read_write> = var private, read_write
|
%v1:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,16 +123,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) {
|
||||||
auto* expr = Mul(Call("my_func"), 4_u);
|
auto* expr = Mul(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = mul %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = mul %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,11 +146,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundMultiply) {
|
||||||
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kMultiply);
|
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kMultiply);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, u32, read_write> = var private, read_write
|
%v1:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -157,16 +169,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) {
|
||||||
auto* expr = Div(Call("my_func"), 4_u);
|
auto* expr = Div(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = div %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = div %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,11 +192,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundDiv) {
|
||||||
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kDivide);
|
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kDivide);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, u32, read_write> = var private, read_write
|
%v1:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,16 +215,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) {
|
||||||
auto* expr = Mod(Call("my_func"), 4_u);
|
auto* expr = Mod(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = mod %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = mod %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,11 +238,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundModulo) {
|
||||||
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kModulo);
|
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kModulo);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, u32, read_write> = var private, read_write
|
%v1:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -241,16 +261,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) {
|
||||||
auto* expr = And(Call("my_func"), 4_u);
|
auto* expr = And(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = and %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = and %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,11 +284,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundAnd) {
|
||||||
auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kAnd);
|
auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kAnd);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, bool, read_write> = var private, read_write
|
%v1:ref<private, bool, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,16 +307,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) {
|
||||||
auto* expr = Or(Call("my_func"), 4_u);
|
auto* expr = Or(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = or %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = or %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,11 +330,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundOr) {
|
||||||
auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kOr);
|
auto* expr = CompoundAssign("v1", false, ast::BinaryOp::kOr);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, bool, read_write> = var private, read_write
|
%v1:ref<private, bool, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -325,16 +353,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) {
|
||||||
auto* expr = Xor(Call("my_func"), 4_u);
|
auto* expr = Xor(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = xor %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = xor %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,11 +376,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundXor) {
|
||||||
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kXor);
|
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kXor);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, u32, read_write> = var private, read_write
|
%v1:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,11 +399,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) {
|
||||||
auto* expr = LogicalAnd(Call("my_func"), false);
|
auto* expr = LogicalAnd(Call("my_func"), false);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = func my_func():bool
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():bool
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
ret true
|
ret true
|
||||||
func_end
|
func_end
|
||||||
|
@ -402,11 +433,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) {
|
||||||
auto* expr = LogicalOr(Call("my_func"), true);
|
auto* expr = LogicalOr(Call("my_func"), true);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = func my_func():bool
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():bool
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
ret true
|
ret true
|
||||||
func_end
|
func_end
|
||||||
|
@ -438,16 +468,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Equal) {
|
||||||
auto* expr = Equal(Call("my_func"), 4_u);
|
auto* expr = Equal(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:bool = eq %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:bool = eq %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,16 +491,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) {
|
||||||
auto* expr = NotEqual(Call("my_func"), 4_u);
|
auto* expr = NotEqual(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:bool = neq %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:bool = neq %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,16 +514,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) {
|
||||||
auto* expr = LessThan(Call("my_func"), 4_u);
|
auto* expr = LessThan(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:bool = lt %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:bool = lt %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,16 +537,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) {
|
||||||
auto* expr = GreaterThan(Call("my_func"), 4_u);
|
auto* expr = GreaterThan(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:bool = gt %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:bool = gt %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,16 +560,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) {
|
||||||
auto* expr = LessThanEqual(Call("my_func"), 4_u);
|
auto* expr = LessThanEqual(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:bool = lte %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:bool = lte %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,16 +583,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) {
|
||||||
auto* expr = GreaterThanEqual(Call("my_func"), 4_u);
|
auto* expr = GreaterThanEqual(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:bool = gte %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:bool = gte %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,16 +606,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) {
|
||||||
auto* expr = Shl(Call("my_func"), 4_u);
|
auto* expr = Shl(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = shiftl %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = shiftl %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,11 +629,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundShiftLeft) {
|
||||||
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftLeft);
|
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftLeft);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, u32, read_write> = var private, read_write
|
%v1:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -588,16 +652,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) {
|
||||||
auto* expr = Shr(Call("my_func"), 4_u);
|
auto* expr = Shr(Call("my_func"), 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = shiftr %1:u32, 4u
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = shiftr %1:u32, 4u
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,11 +675,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_CompoundShiftRight) {
|
||||||
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftRight);
|
auto* expr = CompoundAssign("v1", 1_u, ast::BinaryOp::kShiftRight);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, u32, read_write> = var private, read_write
|
%v1:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -632,11 +700,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) {
|
||||||
GreaterThan(2.5_f, Div(Call("my_func"), Mul(2.3_f, Call("my_func")))));
|
GreaterThan(2.5_f, Div(Call("my_func"), Mul(2.3_f, Call("my_func")))));
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = func my_func():f32
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():f32
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
ret 0.0f
|
ret 0.0f
|
||||||
func_end
|
func_end
|
||||||
|
@ -674,11 +741,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound_WithConstEval) {
|
||||||
GreaterThan(2.5_f, Div(10_f, Mul(2.3_f, 9.4_f)))));
|
GreaterThan(2.5_f, Div(10_f, Mul(2.3_f, 9.4_f)))));
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = func my_func():bool
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():bool
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
ret true
|
ret true
|
||||||
func_end
|
func_end
|
||||||
|
|
|
@ -32,16 +32,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Bitcast) {
|
||||||
auto* expr = Bitcast<f32>(Call("my_func"));
|
auto* expr = Bitcast<f32>(Call("my_func"));
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():f32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 0.0f
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:f32 = call my_func
|
||||||
|
%tint_symbol:f32 = bitcast %1:f32
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:f32 = call my_func
|
|
||||||
%2:f32 = bitcast %1:f32
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,14 +57,15 @@ TEST_F(IR_BuilderImplTest, EmitStatement_Discard) {
|
||||||
create<ast::StageAttribute>(ast::PipelineStage::kFragment),
|
create<ast::StageAttribute>(ast::PipelineStage::kFragment),
|
||||||
});
|
});
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
b.EmitStatement(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func test_function():void [@fragment]
|
||||||
|
%fn2 = block
|
||||||
|
discard
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(discard
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,16 +74,20 @@ TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) {
|
||||||
|
|
||||||
auto* stmt = CallStmt(Call("my_func", Mul(2_a, 3_a)));
|
auto* stmt = CallStmt(Call("my_func", Mul(2_a, 3_a)));
|
||||||
WrapInFunction(stmt);
|
WrapInFunction(stmt);
|
||||||
|
auto m = Build();
|
||||||
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():void
|
||||||
|
%fn2 = block
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
InjectFlowBlock();
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
b.EmitStatement(stmt);
|
%fn4 = block
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
%1:void = call my_func, 6.0f
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:void = call my_func, 6.0f
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,12 +96,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Convert) {
|
||||||
auto* expr = Call(ty.f32(), i);
|
auto* expr = Call(ty.f32(), i);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
ASSERT_TRUE(r);
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%i:ref<private, i32, read_write> = var private, read_write, 1i
|
%i:ref<private, i32, read_write> = var private, read_write, 1i
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,12 +117,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_ConstructEmpty) {
|
||||||
auto* expr = vec3(ty.f32());
|
auto* expr = vec3(ty.f32());
|
||||||
GlobalVar("i", builtin::AddressSpace::kPrivate, expr);
|
GlobalVar("i", builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
ASSERT_TRUE(r);
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%i:ref<private, vec3<f32>, read_write> = var private, read_write, vec3<f32> 0.0f
|
%i:ref<private, vec3<f32>, read_write> = var private, read_write, vec3<f32> 0.0f
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,12 +133,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Construct) {
|
||||||
auto* expr = vec3(ty.f32(), 2_f, 3_f, i);
|
auto* expr = vec3(ty.f32(), 2_f, 3_f, i);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
ASSERT_TRUE(r);
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%i:ref<private, f32, read_write> = var private, read_write, 1.0f
|
%i:ref<private, f32, read_write> = var private, read_write, 1.0f
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,26 @@
|
||||||
#include "src/tint/ast/case_selector.h"
|
#include "src/tint/ast/case_selector.h"
|
||||||
#include "src/tint/ast/int_literal_expression.h"
|
#include "src/tint/ast/int_literal_expression.h"
|
||||||
#include "src/tint/constant/scalar.h"
|
#include "src/tint/constant/scalar.h"
|
||||||
|
#include "src/tint/ir/block.h"
|
||||||
|
#include "src/tint/ir/constant.h"
|
||||||
|
#include "src/tint/ir/var.h"
|
||||||
|
|
||||||
namespace tint::ir {
|
namespace tint::ir {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
Value* GlobalVarInitializer(const Module& m) {
|
||||||
|
if (m.root_block->instructions.Length() == 0u) {
|
||||||
|
ADD_FAILURE() << "m.root_block has no instruction";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto* var = m.root_block->instructions[0]->As<ir::Var>();
|
||||||
|
if (!var) {
|
||||||
|
ADD_FAILURE() << "m.root_block.instructions[0] was not a var";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return var->initializer;
|
||||||
|
}
|
||||||
|
|
||||||
using namespace tint::number_suffixes; // NOLINT
|
using namespace tint::number_suffixes; // NOLINT
|
||||||
|
|
||||||
using IR_BuilderImplTest = TestHelper;
|
using IR_BuilderImplTest = TestHelper;
|
||||||
|
@ -30,12 +46,12 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_Bool_True) {
|
||||||
auto* expr = Expr(true);
|
auto* expr = Expr(true);
|
||||||
GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, expr);
|
GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
auto r = b.EmitLiteral(expr);
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
|
||||||
|
|
||||||
ASSERT_TRUE(r.Get()->Is<Constant>());
|
auto* init = GlobalVarInitializer(m.Get());
|
||||||
auto* val = r.Get()->As<Constant>()->value;
|
ASSERT_TRUE(Is<Constant>(init));
|
||||||
|
auto* val = init->As<Constant>()->value;
|
||||||
EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
|
EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
|
||||||
EXPECT_TRUE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
|
EXPECT_TRUE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
|
||||||
}
|
}
|
||||||
|
@ -44,12 +60,12 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_Bool_False) {
|
||||||
auto* expr = Expr(false);
|
auto* expr = Expr(false);
|
||||||
GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, expr);
|
GlobalVar("a", ty.bool_(), builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
auto r = b.EmitLiteral(expr);
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
|
||||||
|
|
||||||
ASSERT_TRUE(r.Get()->Is<Constant>());
|
auto* init = GlobalVarInitializer(m.Get());
|
||||||
auto* val = r.Get()->As<Constant>()->value;
|
ASSERT_TRUE(Is<Constant>(init));
|
||||||
|
auto* val = init->As<Constant>()->value;
|
||||||
EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
|
EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
|
||||||
EXPECT_FALSE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
|
EXPECT_FALSE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
|
||||||
}
|
}
|
||||||
|
@ -58,12 +74,12 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_F32) {
|
||||||
auto* expr = Expr(1.2_f);
|
auto* expr = Expr(1.2_f);
|
||||||
GlobalVar("a", ty.f32(), builtin::AddressSpace::kPrivate, expr);
|
GlobalVar("a", ty.f32(), builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
auto r = b.EmitLiteral(expr);
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
|
||||||
|
|
||||||
ASSERT_TRUE(r.Get()->Is<Constant>());
|
auto* init = GlobalVarInitializer(m.Get());
|
||||||
auto* val = r.Get()->As<Constant>()->value;
|
ASSERT_TRUE(Is<Constant>(init));
|
||||||
|
auto* val = init->As<Constant>()->value;
|
||||||
EXPECT_TRUE(val->Is<constant::Scalar<f32>>());
|
EXPECT_TRUE(val->Is<constant::Scalar<f32>>());
|
||||||
EXPECT_EQ(1.2_f, val->As<constant::Scalar<f32>>()->ValueAs<f32>());
|
EXPECT_EQ(1.2_f, val->As<constant::Scalar<f32>>()->ValueAs<f32>());
|
||||||
}
|
}
|
||||||
|
@ -73,12 +89,12 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_F16) {
|
||||||
auto* expr = Expr(1.2_h);
|
auto* expr = Expr(1.2_h);
|
||||||
GlobalVar("a", ty.f16(), builtin::AddressSpace::kPrivate, expr);
|
GlobalVar("a", ty.f16(), builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
auto r = b.EmitLiteral(expr);
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
|
||||||
|
|
||||||
ASSERT_TRUE(r.Get()->Is<Constant>());
|
auto* init = GlobalVarInitializer(m.Get());
|
||||||
auto* val = r.Get()->As<Constant>()->value;
|
ASSERT_TRUE(Is<Constant>(init));
|
||||||
|
auto* val = init->As<Constant>()->value;
|
||||||
EXPECT_TRUE(val->Is<constant::Scalar<f16>>());
|
EXPECT_TRUE(val->Is<constant::Scalar<f16>>());
|
||||||
EXPECT_EQ(1.2_h, val->As<constant::Scalar<f16>>()->ValueAs<f32>());
|
EXPECT_EQ(1.2_h, val->As<constant::Scalar<f16>>()->ValueAs<f32>());
|
||||||
}
|
}
|
||||||
|
@ -87,12 +103,12 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_I32) {
|
||||||
auto* expr = Expr(-2_i);
|
auto* expr = Expr(-2_i);
|
||||||
GlobalVar("a", ty.i32(), builtin::AddressSpace::kPrivate, expr);
|
GlobalVar("a", ty.i32(), builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
auto r = b.EmitLiteral(expr);
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
|
||||||
|
|
||||||
ASSERT_TRUE(r.Get()->Is<Constant>());
|
auto* init = GlobalVarInitializer(m.Get());
|
||||||
auto* val = r.Get()->As<Constant>()->value;
|
ASSERT_TRUE(Is<Constant>(init));
|
||||||
|
auto* val = init->As<Constant>()->value;
|
||||||
EXPECT_TRUE(val->Is<constant::Scalar<i32>>());
|
EXPECT_TRUE(val->Is<constant::Scalar<i32>>());
|
||||||
EXPECT_EQ(-2_i, val->As<constant::Scalar<i32>>()->ValueAs<f32>());
|
EXPECT_EQ(-2_i, val->As<constant::Scalar<i32>>()->ValueAs<f32>());
|
||||||
}
|
}
|
||||||
|
@ -101,12 +117,12 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_U32) {
|
||||||
auto* expr = Expr(2_u);
|
auto* expr = Expr(2_u);
|
||||||
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, expr);
|
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
auto r = b.EmitLiteral(expr);
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
|
||||||
|
|
||||||
ASSERT_TRUE(r.Get()->Is<Constant>());
|
auto* init = GlobalVarInitializer(m.Get());
|
||||||
auto* val = r.Get()->As<Constant>()->value;
|
ASSERT_TRUE(Is<Constant>(init));
|
||||||
|
auto* val = init->As<Constant>()->value;
|
||||||
EXPECT_TRUE(val->Is<constant::Scalar<u32>>());
|
EXPECT_TRUE(val->Is<constant::Scalar<u32>>());
|
||||||
EXPECT_EQ(2_u, val->As<constant::Scalar<u32>>()->ValueAs<f32>());
|
EXPECT_EQ(2_u, val->As<constant::Scalar<u32>>()->ValueAs<f32>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_MaterializedCall) {
|
||||||
|
|
||||||
Func("test_function", {}, ty.f32(), expr, utils::Empty);
|
Func("test_function", {}, ty.f32(), expr, utils::Empty);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = func test_function():f32
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func test_function():f32
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
ret 2.0f
|
ret 2.0f
|
||||||
func_end
|
func_end
|
||||||
|
|
|
@ -32,11 +32,10 @@ TEST_F(IR_BuilderImplTest, EmitStatement_Assign) {
|
||||||
auto* expr = Assign("a", 4_u);
|
auto* expr = Assign("a", 4_u);
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%a:ref<private, u32, read_write> = var private, read_write
|
%a:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2022 The Tint Authors.
|
// Copyright 2023 The Tint Authors.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -18,31 +18,59 @@
|
||||||
#include "src/tint/ast/case_selector.h"
|
#include "src/tint/ast/case_selector.h"
|
||||||
#include "src/tint/ast/int_literal_expression.h"
|
#include "src/tint/ast/int_literal_expression.h"
|
||||||
#include "src/tint/constant/scalar.h"
|
#include "src/tint/constant/scalar.h"
|
||||||
|
#include "src/tint/ir/block.h"
|
||||||
|
#include "src/tint/ir/function_terminator.h"
|
||||||
|
#include "src/tint/ir/if.h"
|
||||||
|
#include "src/tint/ir/loop.h"
|
||||||
|
#include "src/tint/ir/switch.h"
|
||||||
|
|
||||||
namespace tint::ir {
|
namespace tint::ir {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
/// Looks for the flow node with the given type T.
|
||||||
|
/// If no flow node is found, then nullptr is returned.
|
||||||
|
/// If multiple flow nodes are found with the type T, then an error is raised and the first is
|
||||||
|
/// returned.
|
||||||
|
template <typename T>
|
||||||
|
const T* FindSingleFlowNode(const Module& mod) {
|
||||||
|
const T* found = nullptr;
|
||||||
|
size_t count = 0;
|
||||||
|
for (auto* node : mod.flow_nodes.Objects()) {
|
||||||
|
if (auto* as = node->As<T>()) {
|
||||||
|
count++;
|
||||||
|
if (!found) {
|
||||||
|
found = as;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count > 1) {
|
||||||
|
ADD_FAILURE() << "FindSingleFlowNode() found " << count << " nodes of type "
|
||||||
|
<< utils::TypeInfo::Of<T>().name;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
using namespace tint::number_suffixes; // NOLINT
|
using namespace tint::number_suffixes; // NOLINT
|
||||||
|
|
||||||
using IR_BuilderImplTest = TestHelper;
|
using IR_BuilderImplTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(IR_BuilderImplTest, Func) {
|
TEST_F(IR_BuilderImplTest, Func) {
|
||||||
Func("f", utils::Empty, ty.void_(), utils::Empty);
|
Func("f", utils::Empty, ty.void_(), utils::Empty);
|
||||||
auto r = Build();
|
|
||||||
ASSERT_TRUE(r) << Error();
|
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
ASSERT_EQ(0u, m.entry_points.Length());
|
auto m = Build();
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
|
|
||||||
auto* f = m.functions[0];
|
ASSERT_EQ(0u, m->entry_points.Length());
|
||||||
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
|
|
||||||
|
auto* f = m->functions[0];
|
||||||
ASSERT_NE(f->start_target, nullptr);
|
ASSERT_NE(f->start_target, nullptr);
|
||||||
ASSERT_NE(f->end_target, nullptr);
|
ASSERT_NE(f->end_target, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(1u, f->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, f->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, f->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, f->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = func f():void
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func f():void
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
ret
|
ret
|
||||||
func_end
|
func_end
|
||||||
|
@ -53,33 +81,28 @@ func_end
|
||||||
TEST_F(IR_BuilderImplTest, EntryPoint) {
|
TEST_F(IR_BuilderImplTest, EntryPoint) {
|
||||||
Func("f", utils::Empty, ty.void_(), utils::Empty,
|
Func("f", utils::Empty, ty.void_(), utils::Empty,
|
||||||
utils::Vector{Stage(ast::PipelineStage::kFragment)});
|
utils::Vector{Stage(ast::PipelineStage::kFragment)});
|
||||||
auto r = Build();
|
|
||||||
ASSERT_TRUE(r) << Error();
|
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.entry_points.Length());
|
auto m = Build();
|
||||||
EXPECT_EQ(m.functions[0], m.entry_points[0]);
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
|
|
||||||
|
ASSERT_EQ(1u, m->entry_points.Length());
|
||||||
|
EXPECT_EQ(m->functions[0], m->entry_points[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_BuilderImplTest, IfStatement) {
|
TEST_F(IR_BuilderImplTest, IfStatement) {
|
||||||
auto* ast_if = If(true, Block(), Else(Block()));
|
auto* ast_if = If(true, Block(), Else(Block()));
|
||||||
WrapInFunction(ast_if);
|
WrapInFunction(ast_if);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_if, nullptr);
|
|
||||||
EXPECT_TRUE(ir_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* flow = ir_if->As<ir::If>();
|
|
||||||
ASSERT_NE(flow->true_.target, nullptr);
|
ASSERT_NE(flow->true_.target, nullptr);
|
||||||
ASSERT_NE(flow->false_.target, nullptr);
|
ASSERT_NE(flow->false_.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
|
||||||
|
@ -88,7 +111,7 @@ TEST_F(IR_BuilderImplTest, IfStatement) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -114,21 +137,16 @@ TEST_F(IR_BuilderImplTest, IfStatement_TrueReturns) {
|
||||||
auto* ast_if = If(true, Block(Return()));
|
auto* ast_if = If(true, Block(Return()));
|
||||||
WrapInFunction(ast_if);
|
WrapInFunction(ast_if);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_if, nullptr);
|
|
||||||
EXPECT_TRUE(ir_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* flow = ir_if->As<ir::If>();
|
|
||||||
ASSERT_NE(flow->true_.target, nullptr);
|
ASSERT_NE(flow->true_.target, nullptr);
|
||||||
ASSERT_NE(flow->false_.target, nullptr);
|
ASSERT_NE(flow->false_.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
|
||||||
|
@ -137,7 +155,7 @@ TEST_F(IR_BuilderImplTest, IfStatement_TrueReturns) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -162,21 +180,16 @@ TEST_F(IR_BuilderImplTest, IfStatement_FalseReturns) {
|
||||||
auto* ast_if = If(true, Block(), Else(Block(Return())));
|
auto* ast_if = If(true, Block(), Else(Block(Return())));
|
||||||
WrapInFunction(ast_if);
|
WrapInFunction(ast_if);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_if, nullptr);
|
|
||||||
EXPECT_TRUE(ir_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* flow = ir_if->As<ir::If>();
|
|
||||||
ASSERT_NE(flow->true_.target, nullptr);
|
ASSERT_NE(flow->true_.target, nullptr);
|
||||||
ASSERT_NE(flow->false_.target, nullptr);
|
ASSERT_NE(flow->false_.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
|
||||||
|
@ -185,7 +198,7 @@ TEST_F(IR_BuilderImplTest, IfStatement_FalseReturns) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -210,21 +223,16 @@ TEST_F(IR_BuilderImplTest, IfStatement_BothReturn) {
|
||||||
auto* ast_if = If(true, Block(Return()), Else(Block(Return())));
|
auto* ast_if = If(true, Block(Return()), Else(Block(Return())));
|
||||||
WrapInFunction(ast_if);
|
WrapInFunction(ast_if);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_if, nullptr);
|
|
||||||
EXPECT_TRUE(ir_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* flow = ir_if->As<ir::If>();
|
|
||||||
ASSERT_NE(flow->true_.target, nullptr);
|
ASSERT_NE(flow->true_.target, nullptr);
|
||||||
ASSERT_NE(flow->false_.target, nullptr);
|
ASSERT_NE(flow->false_.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->true_.target->inbound_branches.Length());
|
||||||
|
@ -233,7 +241,7 @@ TEST_F(IR_BuilderImplTest, IfStatement_BothReturn) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -255,29 +263,21 @@ TEST_F(IR_BuilderImplTest, IfStatement_JumpChainToMerge) {
|
||||||
auto* ast_if = If(true, Block(ast_loop));
|
auto* ast_if = If(true, Block(ast_loop));
|
||||||
WrapInFunction(ast_if);
|
WrapInFunction(ast_if);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* if_flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_if, nullptr);
|
|
||||||
EXPECT_TRUE(ir_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* if_flow = ir_if->As<ir::If>();
|
|
||||||
ASSERT_NE(if_flow->true_.target, nullptr);
|
ASSERT_NE(if_flow->true_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->false_.target, nullptr);
|
ASSERT_NE(if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->merge.target, nullptr);
|
ASSERT_NE(if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_loop = FlowNodeForAstNode(ast_loop);
|
auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_loop, nullptr);
|
ASSERT_NE(loop_flow, nullptr);
|
||||||
EXPECT_TRUE(ir_loop->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* loop_flow = ir_loop->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow->start.target, nullptr);
|
ASSERT_NE(loop_flow->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->merge.target, nullptr);
|
ASSERT_NE(loop_flow->merge.target, nullptr);
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -312,21 +312,16 @@ TEST_F(IR_BuilderImplTest, Loop_WithBreak) {
|
||||||
auto* ast_loop = Loop(Block(Break()));
|
auto* ast_loop = Loop(Block(Break()));
|
||||||
WrapInFunction(ast_loop);
|
WrapInFunction(ast_loop);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_loop = FlowNodeForAstNode(ast_loop);
|
auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_loop, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* flow = ir_loop->As<ir::Loop>();
|
|
||||||
ASSERT_NE(flow->start.target, nullptr);
|
ASSERT_NE(flow->start.target, nullptr);
|
||||||
ASSERT_NE(flow->continuing.target, nullptr);
|
ASSERT_NE(flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, flow->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, flow->start.target->inbound_branches.Length());
|
||||||
|
@ -335,7 +330,7 @@ TEST_F(IR_BuilderImplTest, Loop_WithBreak) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -358,30 +353,21 @@ TEST_F(IR_BuilderImplTest, Loop_WithContinue) {
|
||||||
auto* ast_loop = Loop(Block(ast_if, Continue()));
|
auto* ast_loop = Loop(Block(ast_if, Continue()));
|
||||||
WrapInFunction(ast_loop);
|
WrapInFunction(ast_loop);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_loop = FlowNodeForAstNode(ast_loop);
|
auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_loop, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* loop_flow = ir_loop->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow->start.target, nullptr);
|
ASSERT_NE(loop_flow->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->merge.target, nullptr);
|
ASSERT_NE(loop_flow->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* if_flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_if, nullptr);
|
|
||||||
ASSERT_TRUE(ir_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* if_flow = ir_if->As<ir::If>();
|
|
||||||
ASSERT_NE(if_flow->true_.target, nullptr);
|
ASSERT_NE(if_flow->true_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->false_.target, nullptr);
|
ASSERT_NE(if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->merge.target, nullptr);
|
ASSERT_NE(if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
||||||
|
@ -394,7 +380,7 @@ TEST_F(IR_BuilderImplTest, Loop_WithContinue) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -434,30 +420,21 @@ TEST_F(IR_BuilderImplTest, Loop_WithContinuing_BreakIf) {
|
||||||
auto* ast_loop = Loop(Block(), Block(ast_break_if));
|
auto* ast_loop = Loop(Block(), Block(ast_break_if));
|
||||||
WrapInFunction(ast_loop);
|
WrapInFunction(ast_loop);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_loop = FlowNodeForAstNode(ast_loop);
|
auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_loop, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* loop_flow = ir_loop->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow->start.target, nullptr);
|
ASSERT_NE(loop_flow->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->merge.target, nullptr);
|
ASSERT_NE(loop_flow->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_break_if = FlowNodeForAstNode(ast_break_if);
|
auto* break_if_flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_break_if, nullptr);
|
|
||||||
ASSERT_TRUE(ir_break_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* break_if_flow = ir_break_if->As<ir::If>();
|
|
||||||
ASSERT_NE(break_if_flow->true_.target, nullptr);
|
ASSERT_NE(break_if_flow->true_.target, nullptr);
|
||||||
ASSERT_NE(break_if_flow->false_.target, nullptr);
|
ASSERT_NE(break_if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(break_if_flow->merge.target, nullptr);
|
ASSERT_NE(break_if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
||||||
|
@ -470,7 +447,7 @@ TEST_F(IR_BuilderImplTest, Loop_WithContinuing_BreakIf) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -510,30 +487,21 @@ TEST_F(IR_BuilderImplTest, Loop_WithReturn) {
|
||||||
auto* ast_loop = Loop(Block(ast_if, Continue()));
|
auto* ast_loop = Loop(Block(ast_if, Continue()));
|
||||||
WrapInFunction(ast_loop);
|
WrapInFunction(ast_loop);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_loop = FlowNodeForAstNode(ast_loop);
|
auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_loop, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* loop_flow = ir_loop->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow->start.target, nullptr);
|
ASSERT_NE(loop_flow->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->merge.target, nullptr);
|
ASSERT_NE(loop_flow->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* if_flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_if, nullptr);
|
|
||||||
ASSERT_TRUE(ir_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* if_flow = ir_if->As<ir::If>();
|
|
||||||
ASSERT_NE(if_flow->true_.target, nullptr);
|
ASSERT_NE(if_flow->true_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->false_.target, nullptr);
|
ASSERT_NE(if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->merge.target, nullptr);
|
ASSERT_NE(if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
||||||
|
@ -546,7 +514,7 @@ TEST_F(IR_BuilderImplTest, Loop_WithReturn) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -581,21 +549,16 @@ TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn) {
|
||||||
auto* ast_loop = Loop(Block(Return(), Continue()));
|
auto* ast_loop = Loop(Block(Return(), Continue()));
|
||||||
WrapInFunction(ast_loop, If(true, Block(Return())));
|
WrapInFunction(ast_loop, If(true, Block(Return())));
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_loop = FlowNodeForAstNode(ast_loop);
|
auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_loop, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* loop_flow = ir_loop->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow->start.target, nullptr);
|
ASSERT_NE(loop_flow->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->merge.target, nullptr);
|
ASSERT_NE(loop_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
||||||
|
@ -604,7 +567,7 @@ TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -631,33 +594,21 @@ TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn_ContinuingBreakIf) {
|
||||||
auto* ast_if = If(true, Block(Return()));
|
auto* ast_if = If(true, Block(Return()));
|
||||||
WrapInFunction(Block(ast_loop, ast_if));
|
WrapInFunction(Block(ast_loop, ast_if));
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_loop = FlowNodeForAstNode(ast_loop);
|
auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_loop, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* loop_flow = ir_loop->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow->start.target, nullptr);
|
ASSERT_NE(loop_flow->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->merge.target, nullptr);
|
ASSERT_NE(loop_flow->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* break_if_flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
EXPECT_EQ(ir_if, nullptr);
|
|
||||||
|
|
||||||
auto* ir_break_if = FlowNodeForAstNode(ast_break_if);
|
|
||||||
ASSERT_NE(ir_break_if, nullptr);
|
|
||||||
EXPECT_TRUE(ir_break_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* break_if_flow = ir_break_if->As<ir::If>();
|
|
||||||
ASSERT_NE(break_if_flow->true_.target, nullptr);
|
ASSERT_NE(break_if_flow->true_.target, nullptr);
|
||||||
ASSERT_NE(break_if_flow->false_.target, nullptr);
|
ASSERT_NE(break_if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(break_if_flow->merge.target, nullptr);
|
ASSERT_NE(break_if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
||||||
|
@ -667,7 +618,7 @@ TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn_ContinuingBreakIf) {
|
||||||
// This is 1 because only the loop branch happens. The subsequent if return is dead code.
|
// This is 1 because only the loop branch happens. The subsequent if return is dead code.
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -686,30 +637,21 @@ TEST_F(IR_BuilderImplTest, Loop_WithIf_BothBranchesBreak) {
|
||||||
auto* ast_loop = Loop(Block(ast_if, Continue()));
|
auto* ast_loop = Loop(Block(ast_if, Continue()));
|
||||||
WrapInFunction(ast_loop);
|
WrapInFunction(ast_loop);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_loop = FlowNodeForAstNode(ast_loop);
|
auto* loop_flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_loop, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* loop_flow = ir_loop->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow->start.target, nullptr);
|
ASSERT_NE(loop_flow->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
ASSERT_NE(loop_flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow->merge.target, nullptr);
|
ASSERT_NE(loop_flow->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_if = FlowNodeForAstNode(ast_if);
|
auto* if_flow = FindSingleFlowNode<ir::If>(m.Get());
|
||||||
ASSERT_NE(ir_if, nullptr);
|
|
||||||
ASSERT_TRUE(ir_if->Is<ir::If>());
|
|
||||||
|
|
||||||
auto* if_flow = ir_if->As<ir::If>();
|
|
||||||
ASSERT_NE(if_flow->true_.target, nullptr);
|
ASSERT_NE(if_flow->true_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->false_.target, nullptr);
|
ASSERT_NE(if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->merge.target, nullptr);
|
ASSERT_NE(if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
EXPECT_EQ(1u, loop_flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, loop_flow->start.target->inbound_branches.Length());
|
||||||
|
@ -722,7 +664,7 @@ TEST_F(IR_BuilderImplTest, Loop_WithIf_BothBranchesBreak) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -763,76 +705,68 @@ TEST_F(IR_BuilderImplTest, Loop_Nested) {
|
||||||
|
|
||||||
WrapInFunction(ast_loop_a);
|
WrapInFunction(ast_loop_a);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_loop_a = FlowNodeForAstNode(ast_loop_a);
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
ASSERT_NE(ir_loop_a, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop_a->Is<ir::Loop>());
|
auto block_exit = [&](const ir::FlowNode* node) -> const ir::FlowNode* {
|
||||||
auto* loop_flow_a = ir_loop_a->As<ir::Loop>();
|
if (auto* block = As<ir::Block>(node)) {
|
||||||
|
return block->branch.target;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto* loop_flow_a = As<ir::Loop>(m->functions[0]->start_target->branch.target);
|
||||||
|
ASSERT_NE(loop_flow_a, nullptr);
|
||||||
ASSERT_NE(loop_flow_a->start.target, nullptr);
|
ASSERT_NE(loop_flow_a->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow_a->continuing.target, nullptr);
|
ASSERT_NE(loop_flow_a->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow_a->merge.target, nullptr);
|
ASSERT_NE(loop_flow_a->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_loop_b = FlowNodeForAstNode(ast_loop_b);
|
auto* loop_flow_b = As<ir::Loop>(block_exit(loop_flow_a->start.target));
|
||||||
ASSERT_NE(ir_loop_b, nullptr);
|
ASSERT_NE(loop_flow_b, nullptr);
|
||||||
EXPECT_TRUE(ir_loop_b->Is<ir::Loop>());
|
|
||||||
auto* loop_flow_b = ir_loop_b->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow_b->start.target, nullptr);
|
ASSERT_NE(loop_flow_b->start.target, nullptr);
|
||||||
ASSERT_NE(loop_flow_b->continuing.target, nullptr);
|
ASSERT_NE(loop_flow_b->continuing.target, nullptr);
|
||||||
ASSERT_NE(loop_flow_b->merge.target, nullptr);
|
ASSERT_NE(loop_flow_b->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_loop_c = FlowNodeForAstNode(ast_loop_c);
|
auto* if_flow_a = As<ir::If>(block_exit(loop_flow_b->start.target));
|
||||||
ASSERT_NE(ir_loop_c, nullptr);
|
ASSERT_NE(if_flow_a, nullptr);
|
||||||
EXPECT_TRUE(ir_loop_c->Is<ir::Loop>());
|
|
||||||
auto* loop_flow_c = ir_loop_c->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow_c->start.target, nullptr);
|
|
||||||
ASSERT_NE(loop_flow_c->continuing.target, nullptr);
|
|
||||||
ASSERT_NE(loop_flow_c->merge.target, nullptr);
|
|
||||||
|
|
||||||
auto* ir_loop_d = FlowNodeForAstNode(ast_loop_d);
|
|
||||||
ASSERT_NE(ir_loop_d, nullptr);
|
|
||||||
EXPECT_TRUE(ir_loop_d->Is<ir::Loop>());
|
|
||||||
auto* loop_flow_d = ir_loop_d->As<ir::Loop>();
|
|
||||||
ASSERT_NE(loop_flow_d->start.target, nullptr);
|
|
||||||
ASSERT_NE(loop_flow_d->continuing.target, nullptr);
|
|
||||||
ASSERT_NE(loop_flow_d->merge.target, nullptr);
|
|
||||||
|
|
||||||
auto* ir_if_a = FlowNodeForAstNode(ast_if_a);
|
|
||||||
ASSERT_NE(ir_if_a, nullptr);
|
|
||||||
EXPECT_TRUE(ir_if_a->Is<ir::If>());
|
|
||||||
auto* if_flow_a = ir_if_a->As<ir::If>();
|
|
||||||
ASSERT_NE(if_flow_a->true_.target, nullptr);
|
ASSERT_NE(if_flow_a->true_.target, nullptr);
|
||||||
ASSERT_NE(if_flow_a->false_.target, nullptr);
|
ASSERT_NE(if_flow_a->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow_a->merge.target, nullptr);
|
ASSERT_NE(if_flow_a->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_if_b = FlowNodeForAstNode(ast_if_b);
|
auto* if_flow_b = As<ir::If>(block_exit(if_flow_a->merge.target));
|
||||||
ASSERT_NE(ir_if_b, nullptr);
|
ASSERT_NE(if_flow_b, nullptr);
|
||||||
EXPECT_TRUE(ir_if_b->Is<ir::If>());
|
|
||||||
auto* if_flow_b = ir_if_b->As<ir::If>();
|
|
||||||
ASSERT_NE(if_flow_b->true_.target, nullptr);
|
ASSERT_NE(if_flow_b->true_.target, nullptr);
|
||||||
ASSERT_NE(if_flow_b->false_.target, nullptr);
|
ASSERT_NE(if_flow_b->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow_b->merge.target, nullptr);
|
ASSERT_NE(if_flow_b->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_if_c = FlowNodeForAstNode(ast_if_c);
|
auto* loop_flow_c = As<ir::Loop>(block_exit(loop_flow_b->continuing.target));
|
||||||
ASSERT_NE(ir_if_c, nullptr);
|
ASSERT_NE(loop_flow_c, nullptr);
|
||||||
EXPECT_TRUE(ir_if_c->Is<ir::If>());
|
ASSERT_NE(loop_flow_c->start.target, nullptr);
|
||||||
auto* if_flow_c = ir_if_c->As<ir::If>();
|
ASSERT_NE(loop_flow_c->continuing.target, nullptr);
|
||||||
|
ASSERT_NE(loop_flow_c->merge.target, nullptr);
|
||||||
|
|
||||||
|
auto* loop_flow_d = As<ir::Loop>(block_exit(loop_flow_c->merge.target));
|
||||||
|
ASSERT_NE(loop_flow_d, nullptr);
|
||||||
|
ASSERT_NE(loop_flow_d->start.target, nullptr);
|
||||||
|
ASSERT_NE(loop_flow_d->continuing.target, nullptr);
|
||||||
|
ASSERT_NE(loop_flow_d->merge.target, nullptr);
|
||||||
|
|
||||||
|
auto* if_flow_c = As<ir::If>(block_exit(loop_flow_d->continuing.target));
|
||||||
|
ASSERT_NE(if_flow_c, nullptr);
|
||||||
ASSERT_NE(if_flow_c->true_.target, nullptr);
|
ASSERT_NE(if_flow_c->true_.target, nullptr);
|
||||||
ASSERT_NE(if_flow_c->false_.target, nullptr);
|
ASSERT_NE(if_flow_c->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow_c->merge.target, nullptr);
|
ASSERT_NE(if_flow_c->merge.target, nullptr);
|
||||||
|
|
||||||
auto* ir_if_d = FlowNodeForAstNode(ast_if_d);
|
auto* if_flow_d = As<ir::If>(block_exit(loop_flow_b->merge.target));
|
||||||
ASSERT_NE(ir_if_d, nullptr);
|
ASSERT_NE(if_flow_d, nullptr);
|
||||||
EXPECT_TRUE(ir_if_d->Is<ir::If>());
|
|
||||||
auto* if_flow_d = ir_if_d->As<ir::If>();
|
|
||||||
ASSERT_NE(if_flow_d->true_.target, nullptr);
|
ASSERT_NE(if_flow_d->true_.target, nullptr);
|
||||||
ASSERT_NE(if_flow_d->false_.target, nullptr);
|
ASSERT_NE(if_flow_d->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow_d->merge.target, nullptr);
|
ASSERT_NE(if_flow_d->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, loop_flow_a->inbound_branches.Length());
|
EXPECT_EQ(1u, loop_flow_a->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, loop_flow_a->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, loop_flow_a->start.target->inbound_branches.Length());
|
||||||
|
@ -869,7 +803,7 @@ TEST_F(IR_BuilderImplTest, Loop_Nested) {
|
||||||
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->start_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -982,15 +916,10 @@ TEST_F(IR_BuilderImplTest, While) {
|
||||||
auto* ast_while = While(false, Block());
|
auto* ast_while = While(false, Block());
|
||||||
WrapInFunction(ast_while);
|
WrapInFunction(ast_while);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_while = FlowNodeForAstNode(ast_while);
|
auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_while, nullptr);
|
|
||||||
ASSERT_TRUE(ir_while->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* flow = ir_while->As<ir::Loop>();
|
|
||||||
ASSERT_NE(flow->start.target, nullptr);
|
ASSERT_NE(flow->start.target, nullptr);
|
||||||
ASSERT_NE(flow->continuing.target, nullptr);
|
ASSERT_NE(flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
@ -1002,8 +931,8 @@ TEST_F(IR_BuilderImplTest, While) {
|
||||||
ASSERT_NE(if_flow->false_.target, nullptr);
|
ASSERT_NE(if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->merge.target, nullptr);
|
ASSERT_NE(if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
|
@ -1014,7 +943,7 @@ TEST_F(IR_BuilderImplTest, While) {
|
||||||
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
|
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
|
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -1053,15 +982,10 @@ TEST_F(IR_BuilderImplTest, While_Return) {
|
||||||
auto* ast_while = While(true, Block(Return()));
|
auto* ast_while = While(true, Block(Return()));
|
||||||
WrapInFunction(ast_while);
|
WrapInFunction(ast_while);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_while = FlowNodeForAstNode(ast_while);
|
auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_while, nullptr);
|
|
||||||
ASSERT_TRUE(ir_while->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* flow = ir_while->As<ir::Loop>();
|
|
||||||
ASSERT_NE(flow->start.target, nullptr);
|
ASSERT_NE(flow->start.target, nullptr);
|
||||||
ASSERT_NE(flow->continuing.target, nullptr);
|
ASSERT_NE(flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
@ -1073,8 +997,8 @@ TEST_F(IR_BuilderImplTest, While_Return) {
|
||||||
ASSERT_NE(if_flow->false_.target, nullptr);
|
ASSERT_NE(if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->merge.target, nullptr);
|
ASSERT_NE(if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
|
@ -1085,7 +1009,7 @@ TEST_F(IR_BuilderImplTest, While_Return) {
|
||||||
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
|
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
|
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -1132,15 +1056,10 @@ TEST_F(IR_BuilderImplTest, DISABLED_For) {
|
||||||
auto* ast_for = For(Decl(Var("i", ty.i32())), LessThan("i", 10_a), Increment("i"), Block());
|
auto* ast_for = For(Decl(Var("i", ty.i32())), LessThan("i", 10_a), Increment("i"), Block());
|
||||||
WrapInFunction(ast_for);
|
WrapInFunction(ast_for);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_for = FlowNodeForAstNode(ast_for);
|
auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_for, nullptr);
|
|
||||||
ASSERT_TRUE(ir_for->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* flow = ir_for->As<ir::Loop>();
|
|
||||||
ASSERT_NE(flow->start.target, nullptr);
|
ASSERT_NE(flow->start.target, nullptr);
|
||||||
ASSERT_NE(flow->continuing.target, nullptr);
|
ASSERT_NE(flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
@ -1152,8 +1071,8 @@ TEST_F(IR_BuilderImplTest, DISABLED_For) {
|
||||||
ASSERT_NE(if_flow->false_.target, nullptr);
|
ASSERT_NE(if_flow->false_.target, nullptr);
|
||||||
ASSERT_NE(if_flow->merge.target, nullptr);
|
ASSERT_NE(if_flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
|
@ -1164,28 +1083,23 @@ TEST_F(IR_BuilderImplTest, DISABLED_For) {
|
||||||
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
|
EXPECT_EQ(1u, if_flow->false_.target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
|
EXPECT_EQ(1u, if_flow->merge.target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"()");
|
EXPECT_EQ(Disassemble(m.Get()), R"()");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) {
|
TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) {
|
||||||
auto* ast_for = For(nullptr, nullptr, nullptr, Block(Break()));
|
auto* ast_for = For(nullptr, nullptr, nullptr, Block(Break()));
|
||||||
WrapInFunction(ast_for);
|
WrapInFunction(ast_for);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_for = FlowNodeForAstNode(ast_for);
|
auto* flow = FindSingleFlowNode<ir::Loop>(m.Get());
|
||||||
ASSERT_NE(ir_for, nullptr);
|
|
||||||
ASSERT_TRUE(ir_for->Is<ir::Loop>());
|
|
||||||
|
|
||||||
auto* flow = ir_for->As<ir::Loop>();
|
|
||||||
ASSERT_NE(flow->start.target, nullptr);
|
ASSERT_NE(flow->start.target, nullptr);
|
||||||
ASSERT_NE(flow->continuing.target, nullptr);
|
ASSERT_NE(flow->continuing.target, nullptr);
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, flow->start.target->inbound_branches.Length());
|
EXPECT_EQ(2u, flow->start.target->inbound_branches.Length());
|
||||||
|
@ -1193,7 +1107,7 @@ TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) {
|
||||||
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -1218,20 +1132,15 @@ TEST_F(IR_BuilderImplTest, Switch) {
|
||||||
|
|
||||||
WrapInFunction(ast_switch);
|
WrapInFunction(ast_switch);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_switch = FlowNodeForAstNode(ast_switch);
|
auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
|
||||||
ASSERT_NE(ir_switch, nullptr);
|
|
||||||
ASSERT_TRUE(ir_switch->Is<ir::Switch>());
|
|
||||||
|
|
||||||
auto* flow = ir_switch->As<ir::Switch>();
|
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
ASSERT_EQ(3u, flow->cases.Length());
|
ASSERT_EQ(3u, flow->cases.Length());
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
|
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
|
||||||
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
|
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
|
||||||
|
@ -1253,7 +1162,7 @@ TEST_F(IR_BuilderImplTest, Switch) {
|
||||||
EXPECT_EQ(3u, flow->merge.target->inbound_branches.Length());
|
EXPECT_EQ(3u, flow->merge.target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -1287,20 +1196,15 @@ TEST_F(IR_BuilderImplTest, Switch_MultiSelector) {
|
||||||
|
|
||||||
WrapInFunction(ast_switch);
|
WrapInFunction(ast_switch);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_switch = FlowNodeForAstNode(ast_switch);
|
auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
|
||||||
ASSERT_NE(ir_switch, nullptr);
|
|
||||||
ASSERT_TRUE(ir_switch->Is<ir::Switch>());
|
|
||||||
|
|
||||||
auto* flow = ir_switch->As<ir::Switch>();
|
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
ASSERT_EQ(1u, flow->cases.Length());
|
ASSERT_EQ(1u, flow->cases.Length());
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
ASSERT_EQ(3u, flow->cases[0].selectors.Length());
|
ASSERT_EQ(3u, flow->cases[0].selectors.Length());
|
||||||
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
|
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
|
||||||
|
@ -1318,7 +1222,7 @@ TEST_F(IR_BuilderImplTest, Switch_MultiSelector) {
|
||||||
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -1340,20 +1244,15 @@ TEST_F(IR_BuilderImplTest, Switch_OnlyDefault) {
|
||||||
auto* ast_switch = Switch(1_i, utils::Vector{DefaultCase(Block())});
|
auto* ast_switch = Switch(1_i, utils::Vector{DefaultCase(Block())});
|
||||||
WrapInFunction(ast_switch);
|
WrapInFunction(ast_switch);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_switch = FlowNodeForAstNode(ast_switch);
|
auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
|
||||||
ASSERT_NE(ir_switch, nullptr);
|
|
||||||
ASSERT_TRUE(ir_switch->Is<ir::Switch>());
|
|
||||||
|
|
||||||
auto* flow = ir_switch->As<ir::Switch>();
|
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
ASSERT_EQ(1u, flow->cases.Length());
|
ASSERT_EQ(1u, flow->cases.Length());
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
|
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
|
||||||
EXPECT_TRUE(flow->cases[0].selectors[0].IsDefault());
|
EXPECT_TRUE(flow->cases[0].selectors[0].IsDefault());
|
||||||
|
@ -1363,7 +1262,7 @@ TEST_F(IR_BuilderImplTest, Switch_OnlyDefault) {
|
||||||
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
|
EXPECT_EQ(1u, flow->merge.target->inbound_branches.Length());
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -1387,20 +1286,15 @@ TEST_F(IR_BuilderImplTest, Switch_WithBreak) {
|
||||||
DefaultCase(Block())});
|
DefaultCase(Block())});
|
||||||
WrapInFunction(ast_switch);
|
WrapInFunction(ast_switch);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
auto* ir_switch = FlowNodeForAstNode(ast_switch);
|
auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
|
||||||
ASSERT_NE(ir_switch, nullptr);
|
|
||||||
ASSERT_TRUE(ir_switch->Is<ir::Switch>());
|
|
||||||
|
|
||||||
auto* flow = ir_switch->As<ir::Switch>();
|
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
ASSERT_EQ(2u, flow->cases.Length());
|
ASSERT_EQ(2u, flow->cases.Length());
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
|
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
|
||||||
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
|
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
|
||||||
|
@ -1417,7 +1311,7 @@ TEST_F(IR_BuilderImplTest, Switch_WithBreak) {
|
||||||
// This is 1 because the if is dead-code eliminated and the return doesn't happen.
|
// This is 1 because the if is dead-code eliminated and the return doesn't happen.
|
||||||
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(1u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
@ -1446,22 +1340,17 @@ TEST_F(IR_BuilderImplTest, Switch_AllReturn) {
|
||||||
auto* ast_if = If(true, Block(Return()));
|
auto* ast_if = If(true, Block(Return()));
|
||||||
WrapInFunction(ast_switch, ast_if);
|
WrapInFunction(ast_switch, ast_if);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
ASSERT_EQ(FlowNodeForAstNode(ast_if), nullptr);
|
ASSERT_EQ(FindSingleFlowNode<ir::If>(m.Get()), nullptr);
|
||||||
|
|
||||||
auto* ir_switch = FlowNodeForAstNode(ast_switch);
|
auto* flow = FindSingleFlowNode<ir::Switch>(m.Get());
|
||||||
ASSERT_NE(ir_switch, nullptr);
|
|
||||||
ASSERT_TRUE(ir_switch->Is<ir::Switch>());
|
|
||||||
|
|
||||||
auto* flow = ir_switch->As<ir::Switch>();
|
|
||||||
ASSERT_NE(flow->merge.target, nullptr);
|
ASSERT_NE(flow->merge.target, nullptr);
|
||||||
ASSERT_EQ(2u, flow->cases.Length());
|
ASSERT_EQ(2u, flow->cases.Length());
|
||||||
|
|
||||||
ASSERT_EQ(1u, m.functions.Length());
|
ASSERT_EQ(1u, m->functions.Length());
|
||||||
auto* func = m.functions[0];
|
auto* func = m->functions[0];
|
||||||
|
|
||||||
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
|
ASSERT_EQ(1u, flow->cases[0].selectors.Length());
|
||||||
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
|
ASSERT_TRUE(flow->cases[0].selectors[0].val->value->Is<constant::Scalar<tint::i32>>());
|
||||||
|
@ -1477,7 +1366,7 @@ TEST_F(IR_BuilderImplTest, Switch_AllReturn) {
|
||||||
EXPECT_EQ(0u, flow->merge.target->inbound_branches.Length());
|
EXPECT_EQ(0u, flow->merge.target->inbound_branches.Length());
|
||||||
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
EXPECT_EQ(2u, func->end_target->inbound_branches.Length());
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
branch %fn3
|
branch %fn3
|
||||||
|
|
|
@ -31,16 +31,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Not) {
|
||||||
auto* expr = Not(Call("my_func"));
|
auto* expr = Not(Call("my_func"));
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():bool
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret false
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:bool = call my_func
|
||||||
|
%tint_symbol:bool = eq %1:bool, false
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:bool = call my_func
|
|
||||||
%2:bool = eq %1:bool, false
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,16 +54,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Complement) {
|
||||||
auto* expr = Complement(Call("my_func"));
|
auto* expr = Complement(Call("my_func"));
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():u32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 1u
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:u32 = call my_func
|
||||||
|
%tint_symbol:u32 = complement %1:u32
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:u32 = call my_func
|
|
||||||
%2:u32 = complement %1:u32
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,16 +77,21 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Negation) {
|
||||||
auto* expr = Negation(Call("my_func"));
|
auto* expr = Negation(Call("my_func"));
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto& b = CreateBuilder();
|
auto m = Build();
|
||||||
InjectFlowBlock();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto r = b.EmitExpression(expr);
|
|
||||||
ASSERT_THAT(b.Diagnostics(), testing::IsEmpty());
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = func my_func():i32
|
||||||
ASSERT_TRUE(r);
|
%fn2 = block
|
||||||
|
ret 1i
|
||||||
|
func_end
|
||||||
|
|
||||||
|
%fn3 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
|
%fn4 = block
|
||||||
|
%1:i32 = call my_func
|
||||||
|
%tint_symbol:i32 = negation %1:i32
|
||||||
|
ret
|
||||||
|
func_end
|
||||||
|
|
||||||
Disassembler d(b.builder.ir);
|
|
||||||
d.EmitBlockInstructions(b.current_flow_block->As<ir::Block>());
|
|
||||||
EXPECT_EQ(d.AsString(), R"(%1:i32 = call my_func
|
|
||||||
%2:i32 = negation %1:i32
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,11 +101,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Unary_AddressOf) {
|
||||||
auto* expr = Decl(Let("v2", AddressOf("v1")));
|
auto* expr = Decl(Let("v2", AddressOf("v1")));
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, i32, read_write> = var private, read_write
|
%v1:ref<private, i32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,11 +126,10 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Unary_Indirection) {
|
||||||
};
|
};
|
||||||
WrapInFunction(stmts);
|
WrapInFunction(stmts);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%v1:ref<private, i32, read_write> = var private, read_write
|
%v1:ref<private, i32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,10 @@ using IR_BuilderImplTest = TestHelper;
|
||||||
TEST_F(IR_BuilderImplTest, Emit_GlobalVar_NoInit) {
|
TEST_F(IR_BuilderImplTest, Emit_GlobalVar_NoInit) {
|
||||||
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate);
|
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%a:ref<private, u32, read_write> = var private, read_write
|
%a:ref<private, u32, read_write> = var private, read_write
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,11 +44,10 @@ TEST_F(IR_BuilderImplTest, Emit_GlobalVar_Init) {
|
||||||
auto* expr = Expr(2_u);
|
auto* expr = Expr(2_u);
|
||||||
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, expr);
|
GlobalVar("a", ty.u32(), builtin::AddressSpace::kPrivate, expr);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m), R"(%fn1 = block
|
EXPECT_EQ(Disassemble(m.Get()), R"(%fn1 = block
|
||||||
%a:ref<private, u32, read_write> = var private, read_write, 2u
|
%a:ref<private, u32, read_write> = var private, read_write, 2u
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,11 +59,10 @@ TEST_F(IR_BuilderImplTest, Emit_Var_NoInit) {
|
||||||
auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction);
|
auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction);
|
||||||
WrapInFunction(a);
|
WrapInFunction(a);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
%a:ref<function, u32, read_write> = var function, read_write
|
%a:ref<function, u32, read_write> = var function, read_write
|
||||||
|
@ -80,11 +77,10 @@ TEST_F(IR_BuilderImplTest, Emit_Var_Init) {
|
||||||
auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction, expr);
|
auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction, expr);
|
||||||
WrapInFunction(a);
|
WrapInFunction(a);
|
||||||
|
|
||||||
auto r = Build();
|
auto m = Build();
|
||||||
ASSERT_TRUE(r) << Error();
|
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
|
||||||
auto m = r.Move();
|
|
||||||
|
|
||||||
EXPECT_EQ(Disassemble(m),
|
EXPECT_EQ(Disassemble(m.Get()),
|
||||||
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
R"(%fn1 = func test_function():void [@compute @workgroup_size(1, 1, 1)]
|
||||||
%fn2 = block
|
%fn2 = block
|
||||||
%a:ref<function, u32, read_write> = var function, read_write, 2u
|
%a:ref<function, u32, read_write> = var function, read_write, 2u
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/tint/ir/builder.h"
|
||||||
#include "src/tint/ir/test_helper.h"
|
#include "src/tint/ir/test_helper.h"
|
||||||
#include "src/tint/ir/value.h"
|
#include "src/tint/ir/value.h"
|
||||||
|
|
||||||
|
@ -23,11 +24,11 @@ using namespace tint::number_suffixes; // NOLINT
|
||||||
using IR_ConstantTest = TestHelper;
|
using IR_ConstantTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(IR_ConstantTest, f32) {
|
TEST_F(IR_ConstantTest, f32) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
utils::StringStream str;
|
utils::StringStream str;
|
||||||
|
|
||||||
auto* c = b.builder.Constant(1.2_f);
|
auto* c = b.Constant(1.2_f);
|
||||||
EXPECT_EQ(1.2_f, c->value->As<constant::Scalar<f32>>()->ValueAs<f32>());
|
EXPECT_EQ(1.2_f, c->value->As<constant::Scalar<f32>>()->ValueAs<f32>());
|
||||||
|
|
||||||
EXPECT_TRUE(c->value->Is<constant::Scalar<f32>>());
|
EXPECT_TRUE(c->value->Is<constant::Scalar<f32>>());
|
||||||
|
@ -38,11 +39,11 @@ TEST_F(IR_ConstantTest, f32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_ConstantTest, f16) {
|
TEST_F(IR_ConstantTest, f16) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
utils::StringStream str;
|
utils::StringStream str;
|
||||||
|
|
||||||
auto* c = b.builder.Constant(1.1_h);
|
auto* c = b.Constant(1.1_h);
|
||||||
EXPECT_EQ(1.1_h, c->value->As<constant::Scalar<f16>>()->ValueAs<f16>());
|
EXPECT_EQ(1.1_h, c->value->As<constant::Scalar<f16>>()->ValueAs<f16>());
|
||||||
|
|
||||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
||||||
|
@ -53,11 +54,11 @@ TEST_F(IR_ConstantTest, f16) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_ConstantTest, i32) {
|
TEST_F(IR_ConstantTest, i32) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
utils::StringStream str;
|
utils::StringStream str;
|
||||||
|
|
||||||
auto* c = b.builder.Constant(1_i);
|
auto* c = b.Constant(1_i);
|
||||||
EXPECT_EQ(1_i, c->value->As<constant::Scalar<i32>>()->ValueAs<i32>());
|
EXPECT_EQ(1_i, c->value->As<constant::Scalar<i32>>()->ValueAs<i32>());
|
||||||
|
|
||||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
||||||
|
@ -68,11 +69,11 @@ TEST_F(IR_ConstantTest, i32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_ConstantTest, u32) {
|
TEST_F(IR_ConstantTest, u32) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
utils::StringStream str;
|
utils::StringStream str;
|
||||||
|
|
||||||
auto* c = b.builder.Constant(2_u);
|
auto* c = b.Constant(2_u);
|
||||||
EXPECT_EQ(2_u, c->value->As<constant::Scalar<u32>>()->ValueAs<u32>());
|
EXPECT_EQ(2_u, c->value->As<constant::Scalar<u32>>()->ValueAs<u32>());
|
||||||
|
|
||||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
||||||
|
@ -83,18 +84,18 @@ TEST_F(IR_ConstantTest, u32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_ConstantTest, bool) {
|
TEST_F(IR_ConstantTest, bool) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
{
|
{
|
||||||
utils::StringStream str;
|
utils::StringStream str;
|
||||||
|
|
||||||
auto* c = b.builder.Constant(false);
|
auto* c = b.Constant(false);
|
||||||
EXPECT_FALSE(c->value->As<constant::Scalar<bool>>()->ValueAs<bool>());
|
EXPECT_FALSE(c->value->As<constant::Scalar<bool>>()->ValueAs<bool>());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
utils::StringStream str;
|
utils::StringStream str;
|
||||||
auto c = b.builder.Constant(true);
|
auto c = b.Constant(true);
|
||||||
EXPECT_TRUE(c->value->As<constant::Scalar<bool>>()->ValueAs<bool>());
|
EXPECT_TRUE(c->value->As<constant::Scalar<bool>>()->ValueAs<bool>());
|
||||||
|
|
||||||
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/tint/ir/builder.h"
|
||||||
#include "src/tint/ir/instruction.h"
|
#include "src/tint/ir/instruction.h"
|
||||||
#include "src/tint/ir/test_helper.h"
|
#include "src/tint/ir/test_helper.h"
|
||||||
|
|
||||||
|
@ -21,9 +22,9 @@ namespace {
|
||||||
using IR_InstructionTest = TestHelper;
|
using IR_InstructionTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, Discard) {
|
TEST_F(IR_InstructionTest, Discard) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
const auto* inst = b.builder.Discard();
|
const auto* inst = b.Discard();
|
||||||
ASSERT_TRUE(inst->Is<ir::Discard>());
|
ASSERT_TRUE(inst->Is<ir::Discard>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "src/tint/ir/module.h"
|
#include "src/tint/ir/module.h"
|
||||||
#include "src/tint/ir/test_helper.h"
|
#include "src/tint/ir/test_helper.h"
|
||||||
|
#include "src/tint/ir/var.h"
|
||||||
|
|
||||||
namespace tint::ir {
|
namespace tint::ir {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/tint/ir/builder.h"
|
||||||
#include "src/tint/ir/instruction.h"
|
#include "src/tint/ir/instruction.h"
|
||||||
#include "src/tint/ir/test_helper.h"
|
#include "src/tint/ir/test_helper.h"
|
||||||
|
|
||||||
|
@ -23,12 +24,12 @@ using namespace tint::number_suffixes; // NOLINT
|
||||||
using IR_InstructionTest = TestHelper;
|
using IR_InstructionTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateStore) {
|
TEST_F(IR_InstructionTest, CreateStore) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
// TODO(dsinclair): This is wrong, but we don't have anything correct to store too at the
|
// TODO(dsinclair): This is wrong, but we don't have anything correct to store too at the
|
||||||
// moment.
|
// moment.
|
||||||
auto* to = b.builder.Discard();
|
auto* to = b.Discard();
|
||||||
const auto* inst = b.builder.Store(to, b.builder.Constant(4_i));
|
const auto* inst = b.Store(to, b.Constant(4_i));
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Store>());
|
ASSERT_TRUE(inst->Is<Store>());
|
||||||
ASSERT_EQ(inst->to, to);
|
ASSERT_EQ(inst->to, to);
|
||||||
|
@ -40,10 +41,10 @@ TEST_F(IR_InstructionTest, CreateStore) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, Store_Usage) {
|
TEST_F(IR_InstructionTest, Store_Usage) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
auto* to = b.builder.Discard();
|
auto* to = b.Discard();
|
||||||
const auto* inst = b.builder.Store(to, b.builder.Constant(4_i));
|
const auto* inst = b.Store(to, b.Constant(4_i));
|
||||||
|
|
||||||
ASSERT_NE(inst->to, nullptr);
|
ASSERT_NE(inst->to, nullptr);
|
||||||
ASSERT_EQ(inst->to->Usage().Length(), 1u);
|
ASSERT_EQ(inst->to->Usage().Length(), 1u);
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "src/tint/ir/builder_impl.h"
|
|
||||||
#include "src/tint/ir/disassembler.h"
|
#include "src/tint/ir/disassembler.h"
|
||||||
|
#include "src/tint/ir/from_program.h"
|
||||||
#include "src/tint/number.h"
|
#include "src/tint/number.h"
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
#include "src/tint/utils/string_stream.h"
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
@ -36,84 +36,28 @@ class TestHelperBase : public BASE, public ProgramBuilder {
|
||||||
|
|
||||||
~TestHelperBase() override = default;
|
~TestHelperBase() override = default;
|
||||||
|
|
||||||
/// Builds and returns a BuilderImpl from the program.
|
|
||||||
/// @note The builder is only created once. Multiple calls to Build() will
|
|
||||||
/// return the same builder without rebuilding.
|
|
||||||
/// @return the builder
|
|
||||||
BuilderImpl& CreateBuilder() {
|
|
||||||
SetResolveOnBuild(true);
|
|
||||||
|
|
||||||
if (gen_) {
|
|
||||||
return *gen_;
|
|
||||||
}
|
|
||||||
diag::Formatter formatter;
|
|
||||||
|
|
||||||
program_ = std::make_unique<Program>(std::move(*this));
|
|
||||||
[&]() { ASSERT_TRUE(program_->IsValid()) << formatter.format(program_->Diagnostics()); }();
|
|
||||||
gen_ = std::make_unique<BuilderImpl>(program_.get());
|
|
||||||
return *gen_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Injects a flow block into the builder
|
|
||||||
/// @returns the injected block
|
|
||||||
ir::Block* InjectFlowBlock() {
|
|
||||||
auto* block = gen_->builder.CreateBlock();
|
|
||||||
gen_->current_flow_block = block;
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a BuilderImpl without an originating program. This is used for testing the
|
|
||||||
/// expressions which don't require the full builder implementation. The current flow block
|
|
||||||
/// is initialized with an empty block.
|
|
||||||
/// @returns the BuilderImpl for testing.
|
|
||||||
BuilderImpl& CreateEmptyBuilder() {
|
|
||||||
program_ = std::make_unique<Program>();
|
|
||||||
gen_ = std::make_unique<BuilderImpl>(program_.get());
|
|
||||||
gen_->current_flow_block = gen_->builder.CreateBlock();
|
|
||||||
return *gen_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build the module, cleaning up the program before returning.
|
/// Build the module, cleaning up the program before returning.
|
||||||
/// @returns the generated module
|
/// @returns the generated module
|
||||||
utils::Result<Module> Build() {
|
utils::Result<Module, std::string> Build() {
|
||||||
auto& b = CreateBuilder();
|
SetResolveOnBuild(true);
|
||||||
auto m = b.Build();
|
|
||||||
|
|
||||||
// Store the error away in case we need it
|
auto program = std::make_unique<Program>(std::move(*this));
|
||||||
error_ = b.Diagnostics().str();
|
[&]() {
|
||||||
|
diag::Formatter formatter;
|
||||||
|
ASSERT_TRUE(program->IsValid()) << formatter.format(program->Diagnostics());
|
||||||
|
}();
|
||||||
|
|
||||||
// Explicitly remove program to guard against pointers back to ast. Note, this does mean the
|
return FromProgram(program.get());
|
||||||
// BuilderImpl is pointing to an invalid program. We keep the BuilderImpl around because we
|
|
||||||
// need to be able to map from ast pointers to flow nodes in tests.
|
|
||||||
program_ = nullptr;
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @param node the ast node to lookup
|
|
||||||
/// @returns the IR flow node for the given ast node.
|
|
||||||
const ir::FlowNode* FlowNodeForAstNode(const ast::Node* node) const {
|
|
||||||
return gen_->FlowNodeForAstNode(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param mod the module
|
/// @param mod the module
|
||||||
/// @returns the disassembly string of the module
|
/// @returns the disassembly string of the module
|
||||||
std::string Disassemble(Module& mod) const {
|
std::string Disassemble(const Module& mod) const {
|
||||||
Disassembler d(mod);
|
Disassembler d(mod);
|
||||||
return d.Disassemble();
|
return d.Disassemble();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns the error generated during build, if any
|
|
||||||
std::string Error() const { return error_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<BuilderImpl> gen_;
|
|
||||||
|
|
||||||
/// The program built with a call to Build()
|
|
||||||
std::unique_ptr<Program> program_;
|
|
||||||
|
|
||||||
/// Error generated when calling `Build`
|
|
||||||
std::string error_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using TestHelper = TestHelperBase<testing::Test>;
|
using TestHelper = TestHelperBase<testing::Test>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/tint/ir/builder.h"
|
||||||
#include "src/tint/ir/instruction.h"
|
#include "src/tint/ir/instruction.h"
|
||||||
#include "src/tint/ir/test_helper.h"
|
#include "src/tint/ir/test_helper.h"
|
||||||
|
|
||||||
|
@ -23,14 +24,13 @@ using namespace tint::number_suffixes; // NOLINT
|
||||||
using IR_InstructionTest = TestHelper;
|
using IR_InstructionTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateAddressOf) {
|
TEST_F(IR_InstructionTest, CreateAddressOf) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
// TODO(dsinclair): This would be better as an identifier, but works for now.
|
// TODO(dsinclair): This would be better as an identifier, but works for now.
|
||||||
const auto* inst =
|
const auto* inst = b.AddressOf(
|
||||||
b.builder.AddressOf(b.builder.ir.types.Get<type::Pointer>(
|
b.ir.types.Get<type::Pointer>(b.ir.types.Get<type::I32>(), builtin::AddressSpace::kPrivate,
|
||||||
b.builder.ir.types.Get<type::I32>(),
|
builtin::Access::kReadWrite),
|
||||||
builtin::AddressSpace::kPrivate, builtin::Access::kReadWrite),
|
b.Constant(4_i));
|
||||||
b.builder.Constant(4_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Unary>());
|
ASSERT_TRUE(inst->Is<Unary>());
|
||||||
EXPECT_EQ(inst->kind, Unary::Kind::kAddressOf);
|
EXPECT_EQ(inst->kind, Unary::Kind::kAddressOf);
|
||||||
|
@ -44,9 +44,8 @@ TEST_F(IR_InstructionTest, CreateAddressOf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateComplement) {
|
TEST_F(IR_InstructionTest, CreateComplement) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
const auto* inst =
|
const auto* inst = b.Complement(b.ir.types.Get<type::I32>(), b.Constant(4_i));
|
||||||
b.builder.Complement(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Unary>());
|
ASSERT_TRUE(inst->Is<Unary>());
|
||||||
EXPECT_EQ(inst->kind, Unary::Kind::kComplement);
|
EXPECT_EQ(inst->kind, Unary::Kind::kComplement);
|
||||||
|
@ -58,11 +57,10 @@ TEST_F(IR_InstructionTest, CreateComplement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateIndirection) {
|
TEST_F(IR_InstructionTest, CreateIndirection) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
|
|
||||||
// TODO(dsinclair): This would be better as an identifier, but works for now.
|
// TODO(dsinclair): This would be better as an identifier, but works for now.
|
||||||
const auto* inst =
|
const auto* inst = b.Indirection(b.ir.types.Get<type::I32>(), b.Constant(4_i));
|
||||||
b.builder.Indirection(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Unary>());
|
ASSERT_TRUE(inst->Is<Unary>());
|
||||||
EXPECT_EQ(inst->kind, Unary::Kind::kIndirection);
|
EXPECT_EQ(inst->kind, Unary::Kind::kIndirection);
|
||||||
|
@ -74,9 +72,8 @@ TEST_F(IR_InstructionTest, CreateIndirection) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, CreateNegation) {
|
TEST_F(IR_InstructionTest, CreateNegation) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
const auto* inst =
|
const auto* inst = b.Negation(b.ir.types.Get<type::I32>(), b.Constant(4_i));
|
||||||
b.builder.Negation(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
|
|
||||||
|
|
||||||
ASSERT_TRUE(inst->Is<Unary>());
|
ASSERT_TRUE(inst->Is<Unary>());
|
||||||
EXPECT_EQ(inst->kind, Unary::Kind::kNegation);
|
EXPECT_EQ(inst->kind, Unary::Kind::kNegation);
|
||||||
|
@ -88,9 +85,8 @@ TEST_F(IR_InstructionTest, CreateNegation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IR_InstructionTest, Unary_Usage) {
|
TEST_F(IR_InstructionTest, Unary_Usage) {
|
||||||
auto& b = CreateEmptyBuilder();
|
Builder b;
|
||||||
const auto* inst =
|
const auto* inst = b.Negation(b.ir.types.Get<type::I32>(), b.Constant(4_i));
|
||||||
b.builder.Negation(b.builder.ir.types.Get<type::I32>(), b.builder.Constant(4_i));
|
|
||||||
|
|
||||||
EXPECT_EQ(inst->kind, Unary::Kind::kNegation);
|
EXPECT_EQ(inst->kind, Unary::Kind::kNegation);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue