[ir] Renaming Register and Op
This CL renames Register to Value and Op to Instruction.
Bug: tint:1718
Change-Id: Ided22c524213235369aae366a678d8058a516b60
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112041
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index a8644b7..06aa483 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -666,18 +666,18 @@
ir/function.h
ir/if.cc
ir/if.h
+ ir/instruction.cc
+ ir/instruction.h
ir/loop.cc
ir/loop.h
ir/module.cc
ir/module.h
- ir/op.cc
- ir/op.h
- ir/register.cc
- ir/register.h
ir/switch.cc
ir/switch.h
ir/terminator.cc
ir/terminator.h
+ ir/value.cc
+ ir/value.h
)
endif()
@@ -1341,9 +1341,9 @@
if (${TINT_BUILD_IR})
list(APPEND TINT_TEST_SRCS
ir/builder_impl_test.cc
- ir/op_test.cc
- ir/register_test.cc
+ ir/instruction_test.cc
ir/test_helper.h
+ ir/value_test.cc
)
endif()
diff --git a/src/tint/ir/block.h b/src/tint/ir/block.h
index 850c13c..d27fdf4 100644
--- a/src/tint/ir/block.h
+++ b/src/tint/ir/block.h
@@ -16,7 +16,7 @@
#define SRC_TINT_IR_BLOCK_H_
#include "src/tint/ir/flow_node.h"
-#include "src/tint/ir/op.h"
+#include "src/tint/ir/instruction.h"
#include "src/tint/utils/vector.h"
namespace tint::ir {
@@ -33,8 +33,8 @@
/// The node this block branches too.
const FlowNode* branch_target = nullptr;
- /// The operations in the block
- utils::Vector<Op, 16> ops;
+ /// The instructions in the block
+ utils::Vector<Instruction, 16> instructions;
};
} // namespace tint::ir
diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc
index 57a40a7..0403807 100644
--- a/src/tint/ir/builder.cc
+++ b/src/tint/ir/builder.cc
@@ -93,84 +93,84 @@
to->inbound_branches.Push(from);
}
-Register::Id Builder::AllocateRegister() {
- return next_register_id++;
+Value::Id Builder::AllocateValue() {
+ return next_value_id++;
}
-Op Builder::CreateOp(Op::Kind kind, Register lhs, Register rhs) {
- return Op(kind, Register(AllocateRegister()), lhs, rhs);
+Instruction Builder::CreateInstruction(Instruction::Kind kind, Value lhs, Value rhs) {
+ return Instruction(kind, Value(AllocateValue()), lhs, rhs);
}
-Op Builder::And(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kAnd, lhs, rhs);
+Instruction Builder::And(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kAnd, lhs, rhs);
}
-Op Builder::Or(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kOr, lhs, rhs);
+Instruction Builder::Or(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kOr, lhs, rhs);
}
-Op Builder::Xor(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kXor, lhs, rhs);
+Instruction Builder::Xor(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kXor, lhs, rhs);
}
-Op Builder::LogicalAnd(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kLogicalAnd, lhs, rhs);
+Instruction Builder::LogicalAnd(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kLogicalAnd, lhs, rhs);
}
-Op Builder::LogicalOr(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kLogicalOr, lhs, rhs);
+Instruction Builder::LogicalOr(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kLogicalOr, lhs, rhs);
}
-Op Builder::Equal(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kEqual, lhs, rhs);
+Instruction Builder::Equal(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kEqual, lhs, rhs);
}
-Op Builder::NotEqual(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kNotEqual, lhs, rhs);
+Instruction Builder::NotEqual(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kNotEqual, lhs, rhs);
}
-Op Builder::LessThan(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kLessThan, lhs, rhs);
+Instruction Builder::LessThan(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kLessThan, lhs, rhs);
}
-Op Builder::GreaterThan(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kGreaterThan, lhs, rhs);
+Instruction Builder::GreaterThan(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kGreaterThan, lhs, rhs);
}
-Op Builder::LessThanEqual(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kLessThanEqual, lhs, rhs);
+Instruction Builder::LessThanEqual(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kLessThanEqual, lhs, rhs);
}
-Op Builder::GreaterThanEqual(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kGreaterThanEqual, lhs, rhs);
+Instruction Builder::GreaterThanEqual(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kGreaterThanEqual, lhs, rhs);
}
-Op Builder::ShiftLeft(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kShiftLeft, lhs, rhs);
+Instruction Builder::ShiftLeft(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kShiftLeft, lhs, rhs);
}
-Op Builder::ShiftRight(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kShiftRight, lhs, rhs);
+Instruction Builder::ShiftRight(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kShiftRight, lhs, rhs);
}
-Op Builder::Add(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kAdd, lhs, rhs);
+Instruction Builder::Add(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kAdd, lhs, rhs);
}
-Op Builder::Subtract(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kSubtract, lhs, rhs);
+Instruction Builder::Subtract(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kSubtract, lhs, rhs);
}
-Op Builder::Multiply(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kMultiply, lhs, rhs);
+Instruction Builder::Multiply(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kMultiply, lhs, rhs);
}
-Op Builder::Divide(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kDivide, lhs, rhs);
+Instruction Builder::Divide(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kDivide, lhs, rhs);
}
-Op Builder::Modulo(Register lhs, Register rhs) {
- return CreateOp(Op::Kind::kModulo, lhs, rhs);
+Instruction Builder::Modulo(Value lhs, Value rhs) {
+ return CreateInstruction(Instruction::Kind::kModulo, lhs, rhs);
}
} // namespace tint::ir
diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h
index 091aac8..6776d35 100644
--- a/src/tint/ir/builder.h
+++ b/src/tint/ir/builder.h
@@ -17,12 +17,12 @@
#include "src/tint/ir/function.h"
#include "src/tint/ir/if.h"
+#include "src/tint/ir/instruction.h"
#include "src/tint/ir/loop.h"
#include "src/tint/ir/module.h"
-#include "src/tint/ir/op.h"
-#include "src/tint/ir/register.h"
#include "src/tint/ir/switch.h"
#include "src/tint/ir/terminator.h"
+#include "src/tint/ir/value.h"
// Forward Declarations
namespace tint {
@@ -88,124 +88,124 @@
/// @param lhs the left-hand-side of the operation
/// @param rhs the right-hand-side of the operation
/// @returns the operation
- Op CreateOp(Op::Kind kind, Register lhs, Register rhs);
+ Instruction CreateInstruction(Instruction::Kind kind, Value lhs, Value rhs);
/// Creates an And operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op And(Register lhs, Register rhs);
+ Instruction And(Value lhs, Value rhs);
/// Creates an Or operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op Or(Register lhs, Register rhs);
+ Instruction Or(Value lhs, Value rhs);
/// Creates an Xor operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op Xor(Register lhs, Register rhs);
+ Instruction Xor(Value lhs, Value rhs);
/// Creates an LogicalAnd operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op LogicalAnd(Register lhs, Register rhs);
+ Instruction LogicalAnd(Value lhs, Value rhs);
/// Creates an LogicalOr operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op LogicalOr(Register lhs, Register rhs);
+ Instruction LogicalOr(Value lhs, Value rhs);
/// Creates an Equal operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op Equal(Register lhs, Register rhs);
+ Instruction Equal(Value lhs, Value rhs);
/// Creates an NotEqual operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op NotEqual(Register lhs, Register rhs);
+ Instruction NotEqual(Value lhs, Value rhs);
/// Creates an LessThan operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op LessThan(Register lhs, Register rhs);
+ Instruction LessThan(Value lhs, Value rhs);
/// Creates an GreaterThan operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op GreaterThan(Register lhs, Register rhs);
+ Instruction GreaterThan(Value lhs, Value rhs);
/// Creates an LessThanEqual operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op LessThanEqual(Register lhs, Register rhs);
+ Instruction LessThanEqual(Value lhs, Value rhs);
/// Creates an GreaterThanEqual operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op GreaterThanEqual(Register lhs, Register rhs);
+ Instruction GreaterThanEqual(Value lhs, Value rhs);
/// Creates an ShiftLeft operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op ShiftLeft(Register lhs, Register rhs);
+ Instruction ShiftLeft(Value lhs, Value rhs);
/// Creates an ShiftRight operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op ShiftRight(Register lhs, Register rhs);
+ Instruction ShiftRight(Value lhs, Value rhs);
/// Creates an Add operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op Add(Register lhs, Register rhs);
+ Instruction Add(Value lhs, Value rhs);
/// Creates an Subtract operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op Subtract(Register lhs, Register rhs);
+ Instruction Subtract(Value lhs, Value rhs);
/// Creates an Multiply operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op Multiply(Register lhs, Register rhs);
+ Instruction Multiply(Value lhs, Value rhs);
/// Creates an Divide operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op Divide(Register lhs, Register rhs);
+ Instruction Divide(Value lhs, Value rhs);
/// Creates an Modulo operation
/// @param lhs the lhs of the add
/// @param rhs the rhs of the add
/// @returns the operation
- Op Modulo(Register lhs, Register rhs);
+ Instruction Modulo(Value lhs, Value rhs);
- /// @returns a unique register id
- Register::Id AllocateRegister();
+ /// @returns a unique Value id
+ Value::Id AllocateValue();
/// The IR module.
Module ir;
- /// The next register number to allocate
- Register::Id next_register_id = 1;
+ /// The next Value number to allocate
+ Value::Id next_value_id = 1;
};
} // namespace tint::ir
diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc
index 06ed837..3af54f9 100644
--- a/src/tint/ir/builder_impl.cc
+++ b/src/tint/ir/builder_impl.cc
@@ -516,7 +516,7 @@
return true;
}
-utils::Result<Register> BuilderImpl::EmitExpression(const ast::Expression* expr) {
+utils::Result<Value> BuilderImpl::EmitExpression(const ast::Expression* expr) {
return tint::Switch(
expr,
// [&](const ast::IndexAccessorExpression* a) { return EmitIndexAccessor(a); },
@@ -551,7 +551,7 @@
});
}
-utils::Result<Register> BuilderImpl::EmitBinary(const ast::BinaryExpression* expr) {
+utils::Result<Value> BuilderImpl::EmitBinary(const ast::BinaryExpression* expr) {
auto lhs = EmitExpression(expr->lhs);
if (!lhs) {
return utils::Failure;
@@ -562,89 +562,87 @@
return utils::Failure;
}
- Op op;
+ Instruction instr;
switch (expr->op) {
case ast::BinaryOp::kAnd:
- op = builder.And(lhs.Get(), rhs.Get());
+ instr = builder.And(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kOr:
- op = builder.Or(lhs.Get(), rhs.Get());
+ instr = builder.Or(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kXor:
- op = builder.Xor(lhs.Get(), rhs.Get());
+ instr = builder.Xor(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kLogicalAnd:
- op = builder.LogicalAnd(lhs.Get(), rhs.Get());
+ instr = builder.LogicalAnd(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kLogicalOr:
- op = builder.LogicalOr(lhs.Get(), rhs.Get());
+ instr = builder.LogicalOr(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kEqual:
- op = builder.Equal(lhs.Get(), rhs.Get());
+ instr = builder.Equal(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kNotEqual:
- op = builder.NotEqual(lhs.Get(), rhs.Get());
+ instr = builder.NotEqual(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kLessThan:
- op = builder.LessThan(lhs.Get(), rhs.Get());
+ instr = builder.LessThan(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kGreaterThan:
- op = builder.GreaterThan(lhs.Get(), rhs.Get());
+ instr = builder.GreaterThan(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kLessThanEqual:
- op = builder.LessThanEqual(lhs.Get(), rhs.Get());
+ instr = builder.LessThanEqual(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kGreaterThanEqual:
- op = builder.GreaterThanEqual(lhs.Get(), rhs.Get());
+ instr = builder.GreaterThanEqual(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kShiftLeft:
- op = builder.ShiftLeft(lhs.Get(), rhs.Get());
+ instr = builder.ShiftLeft(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kShiftRight:
- op = builder.ShiftRight(lhs.Get(), rhs.Get());
+ instr = builder.ShiftRight(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kAdd:
- op = builder.Add(lhs.Get(), rhs.Get());
+ instr = builder.Add(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kSubtract:
- op = builder.Subtract(lhs.Get(), rhs.Get());
+ instr = builder.Subtract(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kMultiply:
- op = builder.Multiply(lhs.Get(), rhs.Get());
+ instr = builder.Multiply(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kDivide:
- op = builder.Divide(lhs.Get(), rhs.Get());
+ instr = builder.Divide(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kModulo:
- op = builder.Modulo(lhs.Get(), rhs.Get());
+ instr = builder.Modulo(lhs.Get(), rhs.Get());
break;
case ast::BinaryOp::kNone:
TINT_ICE(IR, diagnostics_) << "missing binary operand type";
return utils::Failure;
}
- auto result = op.Result();
- current_flow_block->ops.Push(op);
+ auto result = instr.Result();
+ current_flow_block->instructions.Push(instr);
return result;
}
-utils::Result<Register> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
+utils::Result<Value> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
return tint::Switch( //
lit,
- [&](const ast::BoolLiteralExpression* l) {
- return utils::Result<Register>{Register(l->value)};
- },
+ [&](const ast::BoolLiteralExpression* l) { return utils::Result<Value>{Value(l->value)}; },
[&](const ast::FloatLiteralExpression* l) {
if (l->suffix == ast::FloatLiteralExpression::Suffix::kF) {
- return utils::Result<Register>{Register(f32(static_cast<float>(l->value)))};
+ return utils::Result<Value>{Value(f32(static_cast<float>(l->value)))};
}
- return utils::Result<Register>{Register(f16(static_cast<float>(l->value)))};
+ return utils::Result<Value>{Value(f16(static_cast<float>(l->value)))};
},
[&](const ast::IntLiteralExpression* l) {
if (l->suffix == ast::IntLiteralExpression::Suffix::kI) {
- return utils::Result<Register>{Register(i32(l->value))};
+ return utils::Result<Value>{Value(i32(l->value))};
}
- return utils::Result<Register>{Register(u32(l->value))};
+ return utils::Result<Value>{Value(u32(l->value))};
},
[&](Default) {
diagnostics_.add_warning(tint::diag::System::IR,
diff --git a/src/tint/ir/builder_impl.h b/src/tint/ir/builder_impl.h
index ef5238e..60eda73 100644
--- a/src/tint/ir/builder_impl.h
+++ b/src/tint/ir/builder_impl.h
@@ -23,7 +23,7 @@
#include "src/tint/ir/builder.h"
#include "src/tint/ir/flow_node.h"
#include "src/tint/ir/module.h"
-#include "src/tint/ir/register.h"
+#include "src/tint/ir/value.h"
#include "src/tint/utils/result.h"
// Forward Declarations
@@ -140,7 +140,7 @@
/// Emits an expression
/// @param expr the expression to emit
/// @returns true if successful, false otherwise
- utils::Result<Register> EmitExpression(const ast::Expression* expr);
+ utils::Result<Value> EmitExpression(const ast::Expression* expr);
/// Emits a variable
/// @param var the variable to emit
@@ -149,13 +149,13 @@
/// Emits a binary expression
/// @param expr the binary expression
- /// @returns the register storing the result if successful, utils::Failure otherwise
- utils::Result<Register> EmitBinary(const ast::BinaryExpression* expr);
+ /// @returns the value storing the result if successful, utils::Failure otherwise
+ utils::Result<Value> EmitBinary(const ast::BinaryExpression* expr);
/// Emits a literal expression
/// @param lit the literal to emit
/// @returns true if successful, false otherwise
- utils::Result<Register> EmitLiteral(const ast::LiteralExpression* lit);
+ utils::Result<Value> EmitLiteral(const ast::LiteralExpression* lit);
/// Emits a type
/// @param ty the type to emit
diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc
index 4a1efd5..6c8e496 100644
--- a/src/tint/ir/builder_impl_test.cc
+++ b/src/tint/ir/builder_impl_test.cc
@@ -101,9 +101,9 @@
EXPECT_EQ(flow->merge_target->branch_target, func->end_target);
// Check condition
- auto op = flow->condition;
- ASSERT_TRUE(op.IsBool());
- EXPECT_TRUE(op.AsBool());
+ auto instr = flow->condition;
+ ASSERT_TRUE(instr.IsBool());
+ EXPECT_TRUE(instr.AsBool());
}
TEST_F(IR_BuilderImplTest, IfStatement_TrueReturns) {
@@ -502,9 +502,9 @@
EXPECT_EQ(loop_flow->merge_target->branch_target, nullptr);
// Check condition
- auto op = if_flow->condition;
- ASSERT_TRUE(op.IsBool());
- EXPECT_TRUE(op.AsBool());
+ auto instr = if_flow->condition;
+ ASSERT_TRUE(instr.IsBool());
+ EXPECT_TRUE(instr.AsBool());
}
TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn) {
@@ -947,9 +947,9 @@
EXPECT_EQ(flow->merge_target->branch_target, func->end_target);
// Check condition
- auto op = if_flow->condition;
- ASSERT_TRUE(op.IsBool());
- EXPECT_FALSE(op.AsBool());
+ auto instr = if_flow->condition;
+ ASSERT_TRUE(instr.IsBool());
+ EXPECT_FALSE(instr.AsBool());
}
TEST_F(IR_BuilderImplTest, While_Return) {
@@ -1071,9 +1071,9 @@
EXPECT_EQ(flow->merge_target->branch_target, func->end_target);
// Check condition
- auto op = if_flow->condition;
- ASSERT_TRUE(op.IsBool());
- EXPECT_FALSE(op.AsBool());
+ auto instr = if_flow->condition;
+ ASSERT_TRUE(instr.IsBool());
+ EXPECT_FALSE(instr.AsBool());
}
TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) {
@@ -1171,9 +1171,9 @@
EXPECT_EQ(flow->merge_target->branch_target, func->end_target);
// Check condition
- auto op = flow->condition;
- ASSERT_TRUE(op.IsI32());
- EXPECT_EQ(1_i, op.AsI32());
+ auto instr = flow->condition;
+ ASSERT_TRUE(instr.IsI32());
+ EXPECT_EQ(1_i, instr.AsI32());
}
TEST_F(IR_BuilderImplTest, Switch_OnlyDefault) {
@@ -1402,7 +1402,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 + 4
)");
}
@@ -1413,7 +1413,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 - 4
)");
}
@@ -1424,7 +1424,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 * 4
)");
}
@@ -1435,7 +1435,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 / 4
)");
}
@@ -1446,7 +1446,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 % 4
)");
}
@@ -1457,7 +1457,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 & 4
)");
}
@@ -1468,7 +1468,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 | 4
)");
}
@@ -1479,7 +1479,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 ^ 4
)");
}
@@ -1490,7 +1490,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 && 4
)");
}
@@ -1501,7 +1501,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 || 4
)");
}
@@ -1512,7 +1512,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 == 4
)");
}
@@ -1523,7 +1523,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 != 4
)");
}
@@ -1534,7 +1534,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 < 4
)");
}
@@ -1545,7 +1545,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 > 4
)");
}
@@ -1556,7 +1556,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 <= 4
)");
}
@@ -1567,7 +1567,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >= 4
)");
}
@@ -1578,7 +1578,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 << 4
)");
}
@@ -1589,7 +1589,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >> 4
)");
}
@@ -1601,7 +1601,7 @@
ASSERT_TRUE(r);
Disassembler d;
- d.EmitBlockOps(b.current_flow_block);
+ d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >> 4
%2 = %1 + 9
%3 = 1 < %2
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index a648d68..f98950f 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -61,9 +61,9 @@
return out_;
}
-void Disassembler::EmitBlockOps(const Block* b) {
- for (const auto& op : b->ops) {
- out_ << op << std::endl;
+void Disassembler::EmitBlockInstructions(const Block* b) {
+ for (const auto& instr : b->instructions) {
+ out_ << instr << std::endl;
}
}
@@ -87,7 +87,7 @@
},
[&](const ir::Block* b) {
Indent() << "Block" << std::endl;
- EmitBlockOps(b);
+ EmitBlockInstructions(b);
Walk(b->branch_target);
},
[&](const ir::Switch* s) {
diff --git a/src/tint/ir/disassembler.h b/src/tint/ir/disassembler.h
index 9cb8993..e24524a 100644
--- a/src/tint/ir/disassembler.h
+++ b/src/tint/ir/disassembler.h
@@ -36,9 +36,9 @@
/// @returns the string representation of the module
std::string Disassemble(const Module& mod);
- /// Writes the block ops to the stream
- /// @param b the block containing the ops
- void EmitBlockOps(const Block* b);
+ /// Writes the block instructions to the stream
+ /// @param b the block containing the instructions
+ void EmitBlockInstructions(const Block* b);
/// @returns the string representation
std::string AsString() const { return out_.str(); }
diff --git a/src/tint/ir/if.h b/src/tint/ir/if.h
index 109b990..4b2969d 100644
--- a/src/tint/ir/if.h
+++ b/src/tint/ir/if.h
@@ -17,7 +17,7 @@
#include "src/tint/ast/if_statement.h"
#include "src/tint/ir/flow_node.h"
-#include "src/tint/ir/register.h"
+#include "src/tint/ir/value.h"
// Forward declarations
namespace tint::ir {
@@ -44,8 +44,8 @@
/// An block to reconvert the true/false barnches. The block always exists, but there maybe no
/// branches into it. (e.g. if both branches `return`)
Block* merge_target = nullptr;
- /// Register holding the condition result
- Register condition;
+ /// Value holding the condition result
+ Value condition;
};
} // namespace tint::ir
diff --git a/src/tint/ir/instruction.cc b/src/tint/ir/instruction.cc
new file mode 100644
index 0000000..9460f39
--- /dev/null
+++ b/src/tint/ir/instruction.cc
@@ -0,0 +1,105 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/instruction.h"
+
+namespace tint::ir {
+
+Instruction::Instruction() {}
+
+Instruction::Instruction(Kind kind, Value result, Value lhs, Value rhs)
+ : kind_(kind), result_(result), args_({lhs, rhs}) {}
+
+Instruction::Instruction(const Instruction&) = default;
+
+Instruction::Instruction(Instruction&& instr) = default;
+
+Instruction::~Instruction() = default;
+
+Instruction& Instruction::operator=(const Instruction& instr) = default;
+
+Instruction& Instruction::operator=(Instruction&& instr) = default;
+
+std::ostream& operator<<(std::ostream& out, const Instruction& instr) {
+ out << instr.Result() << " = ";
+ if (instr.HasLHS()) {
+ out << instr.LHS();
+ }
+ out << " ";
+
+ switch (instr.GetKind()) {
+ case Instruction::Kind::kAdd:
+ out << "+";
+ break;
+ case Instruction::Kind::kSubtract:
+ out << "-";
+ break;
+ case Instruction::Kind::kMultiply:
+ out << "*";
+ break;
+ case Instruction::Kind::kDivide:
+ out << "/";
+ break;
+ case Instruction::Kind::kModulo:
+ out << "%";
+ break;
+ case Instruction::Kind::kAnd:
+ out << "&";
+ break;
+ case Instruction::Kind::kOr:
+ out << "|";
+ break;
+ case Instruction::Kind::kXor:
+ out << "^";
+ break;
+ case Instruction::Kind::kLogicalAnd:
+ out << "&&";
+ break;
+ case Instruction::Kind::kLogicalOr:
+ out << "||";
+ break;
+ case Instruction::Kind::kEqual:
+ out << "==";
+ break;
+ case Instruction::Kind::kNotEqual:
+ out << "!=";
+ break;
+ case Instruction::Kind::kLessThan:
+ out << "<";
+ break;
+ case Instruction::Kind::kGreaterThan:
+ out << ">";
+ break;
+ case Instruction::Kind::kLessThanEqual:
+ out << "<=";
+ break;
+ case Instruction::Kind::kGreaterThanEqual:
+ out << ">=";
+ break;
+ case Instruction::Kind::kShiftLeft:
+ out << "<<";
+ break;
+ case Instruction::Kind::kShiftRight:
+ out << ">>";
+ break;
+ }
+
+ if (instr.HasRHS()) {
+ out << " " << instr.RHS();
+ }
+
+ return out;
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/instruction.h b/src/tint/ir/instruction.h
new file mode 100644
index 0000000..b62300c
--- /dev/null
+++ b/src/tint/ir/instruction.h
@@ -0,0 +1,113 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_INSTRUCTION_H_
+#define SRC_TINT_IR_INSTRUCTION_H_
+
+#include <ostream>
+
+#include "src/tint/ir/value.h"
+#include "src/tint/utils/vector.h"
+
+namespace tint::ir {
+
+/// An instruction in the IR.
+class Instruction {
+ public:
+ /// The kind of instruction.
+ enum class Kind {
+ kAdd,
+ kSubtract,
+ kMultiply,
+ kDivide,
+ kModulo,
+
+ kAnd,
+ kOr,
+ kXor,
+
+ kLogicalAnd,
+ kLogicalOr,
+
+ kEqual,
+ kNotEqual,
+ kLessThan,
+ kGreaterThan,
+ kLessThanEqual,
+ kGreaterThanEqual,
+
+ kShiftLeft,
+ kShiftRight
+ };
+
+ /// Constructor
+ Instruction();
+ /// Constructor
+ /// @param kind the kind of instruction
+ /// @param result the result value
+ /// @param lhs the lhs of the instruction
+ /// @param rhs the rhs of the instruction
+ Instruction(Kind kind, Value result, Value lhs, Value rhs);
+ /// Copy constructor
+ /// @param instr the instruction to copy from
+ Instruction(const Instruction& instr);
+ /// Move constructor
+ /// @param instr the instruction to move from
+ Instruction(Instruction&& instr);
+ /// Destructor
+ ~Instruction();
+
+ /// Copy assign
+ /// @param instr the instruction to copy from
+ /// @returns a reference to this
+ Instruction& operator=(const Instruction& instr);
+ /// Move assign
+ /// @param instr the instruction to move from
+ /// @returns a reference to this
+ Instruction& operator=(Instruction&& instr);
+
+ /// @returns the kind of instruction
+ Kind GetKind() const { return kind_; }
+
+ /// @returns the result value for the instruction
+ const Value& Result() const { return result_; }
+
+ /// @returns true if the instruction has a LHS
+ bool HasLHS() const { return args_.Length() >= 1; }
+ /// @returns the left-hand-side value for the instruction
+ const Value& LHS() const {
+ TINT_ASSERT(IR, HasLHS());
+ return args_[0];
+ }
+
+ /// @returns true if the instruction has a RHS
+ bool HasRHS() const { return args_.Length() >= 2; }
+ /// @returns the right-hand-side value for the instruction
+ const Value& RHS() const {
+ TINT_ASSERT(IR, HasRHS());
+ return args_[1];
+ }
+
+ private:
+ Kind kind_;
+
+ Value result_;
+ utils::Vector<Value, 2> args_;
+};
+
+std::ostream& operator<<(std::ostream& out, const Instruction&);
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_INSTRUCTION_H_
diff --git a/src/tint/ir/instruction_test.cc b/src/tint/ir/instruction_test.cc
new file mode 100644
index 0000000..8fdd541
--- /dev/null
+++ b/src/tint/ir/instruction_test.cc
@@ -0,0 +1,494 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <sstream>
+
+#include "src/tint/ir/instruction.h"
+#include "src/tint/ir/test_helper.h"
+
+namespace tint::ir {
+namespace {
+
+using IR_InstructionTest = TestHelper;
+
+TEST_F(IR_InstructionTest, CreateAnd) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.And(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kAnd);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 & 2");
+}
+
+TEST_F(IR_InstructionTest, CreateOr) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.Or(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kOr);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 | 2");
+}
+
+TEST_F(IR_InstructionTest, CreateXor) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.Xor(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kXor);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 ^ 2");
+}
+
+TEST_F(IR_InstructionTest, CreateLogicalAnd) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.LogicalAnd(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kLogicalAnd);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 && 2");
+}
+
+TEST_F(IR_InstructionTest, CreateLogicalOr) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.LogicalOr(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kLogicalOr);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 || 2");
+}
+
+TEST_F(IR_InstructionTest, CreateEqual) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.Equal(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kEqual);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 == 2");
+}
+
+TEST_F(IR_InstructionTest, CreateNotEqual) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.NotEqual(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kNotEqual);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 != 2");
+}
+
+TEST_F(IR_InstructionTest, CreateLessThan) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.LessThan(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kLessThan);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 < 2");
+}
+
+TEST_F(IR_InstructionTest, CreateGreaterThan) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.GreaterThan(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kGreaterThan);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 > 2");
+}
+
+TEST_F(IR_InstructionTest, CreateLessThanEqual) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.LessThanEqual(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kLessThanEqual);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 <= 2");
+}
+
+TEST_F(IR_InstructionTest, CreateGreaterThanEqual) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.GreaterThanEqual(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kGreaterThanEqual);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 >= 2");
+}
+
+TEST_F(IR_InstructionTest, CreateShiftLeft) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.ShiftLeft(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kShiftLeft);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 << 2");
+}
+
+TEST_F(IR_InstructionTest, CreateShiftRight) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.ShiftRight(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kShiftRight);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 >> 2");
+}
+
+TEST_F(IR_InstructionTest, CreateAdd) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.Add(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kAdd);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 + 2");
+}
+
+TEST_F(IR_InstructionTest, CreateSubtract) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.Subtract(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kSubtract);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 - 2");
+}
+
+TEST_F(IR_InstructionTest, CreateMultiply) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.Multiply(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kMultiply);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 * 2");
+}
+
+TEST_F(IR_InstructionTest, CreateDivide) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.Divide(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kDivide);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 / 2");
+}
+
+TEST_F(IR_InstructionTest, CreateModulo) {
+ auto& b = CreateEmptyBuilder();
+
+ b.builder.next_value_id = Value::Id(42);
+ auto instr = b.builder.Modulo(Value(i32(4)), Value(i32(2)));
+
+ EXPECT_EQ(instr.GetKind(), Instruction::Kind::kModulo);
+
+ ASSERT_TRUE(instr.Result().IsTemp());
+ EXPECT_EQ(Value::Id(42), instr.Result().AsId());
+
+ ASSERT_TRUE(instr.HasLHS());
+ auto& lhs = instr.LHS();
+ ASSERT_TRUE(lhs.IsI32());
+ EXPECT_EQ(i32(4), lhs.AsI32());
+
+ ASSERT_TRUE(instr.HasRHS());
+ auto& rhs = instr.RHS();
+ ASSERT_TRUE(rhs.IsI32());
+ EXPECT_EQ(i32(2), rhs.AsI32());
+
+ std::stringstream str;
+ str << instr;
+ EXPECT_EQ(str.str(), "%42 = 4 % 2");
+}
+
+} // namespace
+} // namespace tint::ir
diff --git a/src/tint/ir/op.cc b/src/tint/ir/op.cc
deleted file mode 100644
index 3e6d9936..0000000
--- a/src/tint/ir/op.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2022 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/tint/ir/op.h"
-
-namespace tint::ir {
-
-Op::Op() {}
-
-Op::Op(Kind kind, Register result, Register lhs, Register rhs)
- : kind_(kind), result_(result), args_({lhs, rhs}) {}
-
-Op::Op(const Op&) = default;
-
-Op::Op(Op&& o) = default;
-
-Op::~Op() = default;
-
-Op& Op::operator=(const Op& o) = default;
-
-Op& Op::operator=(Op&& o) = default;
-
-std::ostream& operator<<(std::ostream& out, const Op& op) {
- out << op.Result() << " = ";
- if (op.HasLHS()) {
- out << op.LHS();
- }
- out << " ";
-
- switch (op.GetKind()) {
- case Op::Kind::kAdd:
- out << "+";
- break;
- case Op::Kind::kSubtract:
- out << "-";
- break;
- case Op::Kind::kMultiply:
- out << "*";
- break;
- case Op::Kind::kDivide:
- out << "/";
- break;
- case Op::Kind::kModulo:
- out << "%";
- break;
- case Op::Kind::kAnd:
- out << "&";
- break;
- case Op::Kind::kOr:
- out << "|";
- break;
- case Op::Kind::kXor:
- out << "^";
- break;
- case Op::Kind::kLogicalAnd:
- out << "&&";
- break;
- case Op::Kind::kLogicalOr:
- out << "||";
- break;
- case Op::Kind::kEqual:
- out << "==";
- break;
- case Op::Kind::kNotEqual:
- out << "!=";
- break;
- case Op::Kind::kLessThan:
- out << "<";
- break;
- case Op::Kind::kGreaterThan:
- out << ">";
- break;
- case Op::Kind::kLessThanEqual:
- out << "<=";
- break;
- case Op::Kind::kGreaterThanEqual:
- out << ">=";
- break;
- case Op::Kind::kShiftLeft:
- out << "<<";
- break;
- case Op::Kind::kShiftRight:
- out << ">>";
- break;
- }
-
- if (op.HasRHS()) {
- out << " " << op.RHS();
- }
-
- return out;
-}
-
-} // namespace tint::ir
diff --git a/src/tint/ir/op.h b/src/tint/ir/op.h
deleted file mode 100644
index a9fc78f..0000000
--- a/src/tint/ir/op.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2022 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SRC_TINT_IR_OP_H_
-#define SRC_TINT_IR_OP_H_
-
-#include <ostream>
-
-#include "src/tint/ir/register.h"
-#include "src/tint/utils/vector.h"
-
-namespace tint::ir {
-
-/// An operation in the IR.
-class Op {
- public:
- /// The kind of operation.
- enum class Kind {
- kAdd,
- kSubtract,
- kMultiply,
- kDivide,
- kModulo,
-
- kAnd,
- kOr,
- kXor,
-
- kLogicalAnd,
- kLogicalOr,
-
- kEqual,
- kNotEqual,
- kLessThan,
- kGreaterThan,
- kLessThanEqual,
- kGreaterThanEqual,
-
- kShiftLeft,
- kShiftRight
- };
-
- /// Constructor
- Op();
- /// Constructor
- /// @param kind the kind of operation
- /// @param result the result register
- /// @param lhs the lhs of the operation
- /// @param rhs the rhs of the operation
- Op(Kind kind, Register result, Register lhs, Register rhs);
- /// Copy constructor
- /// @param o the op to copy from
- Op(const Op& o);
- /// Move constructor
- /// @param o the op to move from
- Op(Op&& o);
- /// Destructor
- ~Op();
-
- /// Copy assign
- /// @param o the op to copy from
- /// @returns a reference to this
- Op& operator=(const Op& o);
- /// Move assign
- /// @param o the op to move from
- /// @returns a reference to this
- Op& operator=(Op&& o);
-
- /// @returns the kind of operation
- Kind GetKind() const { return kind_; }
-
- /// @returns the result register for the operation
- const Register& Result() const { return result_; }
-
- /// @returns true if the op has a LHS
- bool HasLHS() const { return args_.Length() >= 1; }
- /// @returns the left-hand-side register for the operation
- const Register& LHS() const {
- TINT_ASSERT(IR, HasLHS());
- return args_[0];
- }
-
- /// @returns true if the op has a RHS
- bool HasRHS() const { return args_.Length() >= 2; }
- /// @returns the right-hand-side register for the operation
- const Register& RHS() const {
- TINT_ASSERT(IR, HasRHS());
- return args_[1];
- }
-
- private:
- Kind kind_;
-
- Register result_;
- utils::Vector<Register, 2> args_;
-};
-
-std::ostream& operator<<(std::ostream& out, const Op&);
-
-} // namespace tint::ir
-
-#endif // SRC_TINT_IR_OP_H_
diff --git a/src/tint/ir/op_test.cc b/src/tint/ir/op_test.cc
deleted file mode 100644
index 01604d1..0000000
--- a/src/tint/ir/op_test.cc
+++ /dev/null
@@ -1,494 +0,0 @@
-// Copyright 2022 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <sstream>
-
-#include "src/tint/ir/op.h"
-#include "src/tint/ir/test_helper.h"
-
-namespace tint::ir {
-namespace {
-
-using IR_OpTest = TestHelper;
-
-TEST_F(IR_OpTest, CreateAnd) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.And(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kAnd);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 & 2");
-}
-
-TEST_F(IR_OpTest, CreateOr) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.Or(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kOr);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 | 2");
-}
-
-TEST_F(IR_OpTest, CreateXor) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.Xor(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kXor);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 ^ 2");
-}
-
-TEST_F(IR_OpTest, CreateLogicalAnd) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.LogicalAnd(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kLogicalAnd);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 && 2");
-}
-
-TEST_F(IR_OpTest, CreateLogicalOr) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.LogicalOr(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kLogicalOr);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 || 2");
-}
-
-TEST_F(IR_OpTest, CreateEqual) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.Equal(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kEqual);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 == 2");
-}
-
-TEST_F(IR_OpTest, CreateNotEqual) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.NotEqual(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kNotEqual);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 != 2");
-}
-
-TEST_F(IR_OpTest, CreateLessThan) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.LessThan(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kLessThan);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 < 2");
-}
-
-TEST_F(IR_OpTest, CreateGreaterThan) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.GreaterThan(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kGreaterThan);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 > 2");
-}
-
-TEST_F(IR_OpTest, CreateLessThanEqual) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.LessThanEqual(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kLessThanEqual);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 <= 2");
-}
-
-TEST_F(IR_OpTest, CreateGreaterThanEqual) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.GreaterThanEqual(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kGreaterThanEqual);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 >= 2");
-}
-
-TEST_F(IR_OpTest, CreateShiftLeft) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.ShiftLeft(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kShiftLeft);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 << 2");
-}
-
-TEST_F(IR_OpTest, CreateShiftRight) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.ShiftRight(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kShiftRight);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 >> 2");
-}
-
-TEST_F(IR_OpTest, CreateAdd) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.Add(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kAdd);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 + 2");
-}
-
-TEST_F(IR_OpTest, CreateSubtract) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.Subtract(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kSubtract);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 - 2");
-}
-
-TEST_F(IR_OpTest, CreateMultiply) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.Multiply(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kMultiply);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 * 2");
-}
-
-TEST_F(IR_OpTest, CreateDivide) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.Divide(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kDivide);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 / 2");
-}
-
-TEST_F(IR_OpTest, CreateModulo) {
- auto& b = CreateEmptyBuilder();
-
- b.builder.next_register_id = Register::Id(42);
- auto o = b.builder.Modulo(Register(i32(4)), Register(i32(2)));
-
- EXPECT_EQ(o.GetKind(), Op::Kind::kModulo);
-
- ASSERT_TRUE(o.Result().IsTemp());
- EXPECT_EQ(Register::Id(42), o.Result().AsId());
-
- ASSERT_TRUE(o.HasLHS());
- auto& lhs = o.LHS();
- ASSERT_TRUE(lhs.IsI32());
- EXPECT_EQ(i32(4), lhs.AsI32());
-
- ASSERT_TRUE(o.HasRHS());
- auto& rhs = o.RHS();
- ASSERT_TRUE(rhs.IsI32());
- EXPECT_EQ(i32(2), rhs.AsI32());
-
- std::stringstream str;
- str << o;
- EXPECT_EQ(str.str(), "%42 = 4 % 2");
-}
-
-} // namespace
-} // namespace tint::ir
diff --git a/src/tint/ir/register.cc b/src/tint/ir/register.cc
deleted file mode 100644
index f3caa76..0000000
--- a/src/tint/ir/register.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2022 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/tint/ir/register.h"
-
-namespace tint::ir {
-
-Register::Register() : kind_(Kind::kUninitialized), data_(Id(0)) {}
-
-Register::Register(Id id) : kind_(Kind::kTemp), data_(id) {}
-
-Register::Register(f32 f) : kind_(Kind::kF32), data_(f) {}
-
-Register::Register(f16 f) : kind_(Kind::kF16), data_(f) {}
-
-Register::Register(u32 u) : kind_(Kind::kU32), data_(u) {}
-
-Register::Register(i32 i) : kind_(Kind::kI32), data_(i) {}
-
-Register::Register(bool b) : kind_(Kind::kBool), data_(b) {}
-
-Register::Register(Symbol s, Id id) : kind_(Kind::kVar), data_(VarData{s, id}) {}
-
-Register::~Register() = default;
-
-Register::Register(const Register& o) = default;
-
-Register::Register(Register&& o) = default;
-
-Register& Register::operator=(const Register& o) = default;
-
-Register& Register::operator=(Register&& o) = default;
-
-std::ostream& operator<<(std::ostream& out, const Register& r) {
- switch (r.GetKind()) {
- case Register::Kind::kTemp:
- out << "%" << std::to_string(r.AsId());
- break;
- case Register::Kind::kF32:
- out << std::to_string(r.AsF32().value);
- break;
- case Register::Kind::kF16:
- out << std::to_string(r.AsF16().value);
- break;
- case Register::Kind::kI32:
- out << std::to_string(r.AsI32().value);
- break;
- case Register::Kind::kU32:
- out << std::to_string(r.AsU32().value);
- break;
- // TODO(dsinclair): Emit the symbol instead of v
- case Register::Kind::kVar:
- out << "%v" << std::to_string(r.AsVarData().id);
- break;
- case Register::Kind::kBool:
- out << (r.AsBool() ? "true" : "false");
- break;
- case Register::Kind::kUninitialized:
- out << "unknown register";
- break;
- }
- return out;
-}
-
-} // namespace tint::ir
diff --git a/src/tint/ir/register.h b/src/tint/ir/register.h
deleted file mode 100644
index d1c41eb..0000000
--- a/src/tint/ir/register.h
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2022 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SRC_TINT_IR_REGISTER_H_
-#define SRC_TINT_IR_REGISTER_H_
-
-#include <ostream>
-#include <variant>
-
-#include "src/tint/number.h"
-#include "src/tint/symbol.h"
-
-namespace tint::ir {
-
-/// Register in the IR. The register can be one of several types these include, but aren't limited
-/// to, `f32`, `u32`, `temp`, `var`. The type of the register determines the type of data stored
-/// in the register.
-class Register {
- public:
- /// A register id.
- using Id = uint32_t;
-
- /// The type of the register
- enum class Kind {
- /// A uninitialized register
- kUninitialized,
- /// A temporary allocated register
- kTemp,
- /// A f32 register
- kF32,
- /// A f16 register
- kF16,
- /// An i32 register
- kI32,
- /// A u32 register
- kU32,
- /// A variable register
- kVar,
- /// A boolean register
- kBool,
- };
-
- /// Stores data for a given variable. There will be multiple `VarData` entries for a given `id`.
- /// The `id` acts like a generation number (although they aren't sequential, they are
- /// increasing). As the variable is stored too a new register will be created and the the `id`
- /// will be incremented.
- struct VarData {
- /// The symbol for the variable
- Symbol sym;
- /// The id for the variable.
- Id id;
- // TODO(dsinclair): Should var type data be stored here along side the variable info?
- };
-
- /// Constructor
- /// Creates a uninitialized register
- Register();
-
- /// Constructor
- /// @param id the id for the register
- explicit Register(Id id);
-
- /// Constructor
- /// @param s the symbol for the register
- /// @param id the id for the register
- Register(Symbol s, Id id);
-
- /// Constructor
- /// @param b the `bool` value to store in the register
- explicit Register(bool b);
-
- /// Constructor
- /// @param f the `f32` value to store in the register
- explicit Register(f32 f);
-
- /// Constructor
- /// @param f the `f16` value to store in the register
- explicit Register(f16 f);
-
- /// Constructor
- /// @param u the `u32` value to store in the register
- explicit Register(u32 u);
-
- /// Constructor
- /// @param i the `i32` value to store in the register
- explicit Register(i32 i);
-
- /// Destructor
- ~Register();
-
- /// Copy constructor
- /// @param o the register to copy from
- Register(const Register& o);
- /// Move constructor
- /// @param o the register to move from
- Register(Register&& o);
-
- /// Copy assign
- /// @param o the register to copy from
- /// @returns this
- Register& operator=(const Register& o);
- /// Move assign
- /// @param o the register to move from
- /// @returns this
- Register& operator=(Register&& o);
-
- /// @returns true if this is a temporary register
- bool IsTemp() const { return kind_ == Kind::kTemp; }
- /// @returns true if this is a f32 register
- bool IsF32() const { return kind_ == Kind::kF32; }
- /// @returns true if this is a f16 register
- bool IsF16() const { return kind_ == Kind::kF16; }
- /// @returns true if this is an i32 register
- bool IsI32() const { return kind_ == Kind::kI32; }
- /// @returns true if this is a u32 register
- bool IsU32() const { return kind_ == Kind::kU32; }
- /// @returns true if this is a var register
- bool IsVar() const { return kind_ == Kind::kVar; }
- /// @returns true if this is a bool register
- bool IsBool() const { return kind_ == Kind::kBool; }
-
- /// @returns the kind of register
- Kind GetKind() const { return kind_; }
-
- /// @returns the register data as a `f32`.
- /// @note, must only be called if `IsF32()` is true
- f32 AsF32() const { return std::get<f32>(data_); }
- /// @returns the register data as a `f16`.
- /// @note, must only be called if `IsF16()` is true
- f16 AsF16() const { return std::get<f16>(data_); }
- /// @returns the register data as an `i32`.
- /// @note, must only be called if `IsI32()` is true
- i32 AsI32() const { return std::get<i32>(data_); }
- /// @returns the register data as a `u32`.
- /// @note, must only be called if `IsU32()` is true
- u32 AsU32() const { return std::get<u32>(data_); }
- /// @returns the register data as an `Id`.
- /// @note, must only be called if `IsTemp()` is true
- Id AsId() const { return std::get<Id>(data_); }
- /// @returns the register data as a `VarData` structure.
- /// @note, must only be called if `IsVar()` is true
- VarData AsVarData() const { return std::get<VarData>(data_); }
- /// @returns the register data as a `bool`.
- /// @note, must only be called if `IsBool()` is true
- bool AsBool() const { return std::get<bool>(data_); }
-
- private:
- /// The type of data stored in this register
- Kind kind_;
- /// The data stored in the register
- std::variant<Id, f32, f16, u32, i32, VarData, bool> data_;
-};
-
-std::ostream& operator<<(std::ostream& out, const Register& r);
-
-} // namespace tint::ir
-
-#endif // SRC_TINT_IR_REGISTER_H_
diff --git a/src/tint/ir/register_test.cc b/src/tint/ir/register_test.cc
deleted file mode 100644
index fb0194f..0000000
--- a/src/tint/ir/register_test.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2022 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <sstream>
-
-#include "src/tint/ir/register.h"
-#include "src/tint/ir/test_helper.h"
-
-namespace tint::ir {
-namespace {
-
-using namespace tint::number_suffixes; // NOLINT
-
-using IR_RegisterTest = TestHelper;
-
-TEST_F(IR_RegisterTest, f32) {
- std::stringstream str;
-
- Register r(1.2_f);
- EXPECT_EQ(1.2_f, r.AsF32());
-
- str << r;
- EXPECT_EQ("1.200000", str.str());
-
- EXPECT_TRUE(r.IsF32());
- EXPECT_FALSE(r.IsF16());
- EXPECT_FALSE(r.IsI32());
- EXPECT_FALSE(r.IsU32());
- EXPECT_FALSE(r.IsTemp());
- EXPECT_FALSE(r.IsVar());
- EXPECT_FALSE(r.IsBool());
-}
-
-TEST_F(IR_RegisterTest, f16) {
- std::stringstream str;
-
- Register r(1.1_h);
- EXPECT_EQ(1.1_h, r.AsF16());
-
- str << r;
- EXPECT_EQ("1.099609", str.str());
-
- EXPECT_FALSE(r.IsF32());
- EXPECT_TRUE(r.IsF16());
- EXPECT_FALSE(r.IsI32());
- EXPECT_FALSE(r.IsU32());
- EXPECT_FALSE(r.IsTemp());
- EXPECT_FALSE(r.IsVar());
- EXPECT_FALSE(r.IsBool());
-}
-
-TEST_F(IR_RegisterTest, i32) {
- std::stringstream str;
-
- Register r(1_i);
- EXPECT_EQ(1_i, r.AsI32());
-
- str << r;
- EXPECT_EQ("1", str.str());
-
- EXPECT_FALSE(r.IsF32());
- EXPECT_FALSE(r.IsF16());
- EXPECT_TRUE(r.IsI32());
- EXPECT_FALSE(r.IsU32());
- EXPECT_FALSE(r.IsTemp());
- EXPECT_FALSE(r.IsVar());
- EXPECT_FALSE(r.IsBool());
-}
-
-TEST_F(IR_RegisterTest, u32) {
- std::stringstream str;
-
- Register r(2_u);
- EXPECT_EQ(2_u, r.AsU32());
-
- str << r;
- EXPECT_EQ("2", str.str());
-
- EXPECT_FALSE(r.IsF32());
- EXPECT_FALSE(r.IsF16());
- EXPECT_FALSE(r.IsI32());
- EXPECT_TRUE(r.IsU32());
- EXPECT_FALSE(r.IsTemp());
- EXPECT_FALSE(r.IsVar());
- EXPECT_FALSE(r.IsBool());
-}
-
-TEST_F(IR_RegisterTest, id) {
- std::stringstream str;
-
- Register r(Register::Id(4));
- EXPECT_EQ(4u, r.AsId());
-
- str << r;
- EXPECT_EQ("%4", str.str());
-
- EXPECT_FALSE(r.IsF32());
- EXPECT_FALSE(r.IsF16());
- EXPECT_FALSE(r.IsI32());
- EXPECT_FALSE(r.IsU32());
- EXPECT_TRUE(r.IsTemp());
- EXPECT_FALSE(r.IsVar());
- EXPECT_FALSE(r.IsBool());
-}
-
-TEST_F(IR_RegisterTest, bool) {
- std::stringstream str;
-
- Register r(false);
- EXPECT_FALSE(r.AsBool());
-
- str << r;
- EXPECT_EQ("false", str.str());
-
- str.str("");
- r = Register(true);
- EXPECT_TRUE(r.AsBool());
-
- str << r;
- EXPECT_EQ("true", str.str());
-
- EXPECT_FALSE(r.IsF32());
- EXPECT_FALSE(r.IsF16());
- EXPECT_FALSE(r.IsI32());
- EXPECT_FALSE(r.IsU32());
- EXPECT_FALSE(r.IsTemp());
- EXPECT_FALSE(r.IsVar());
- EXPECT_TRUE(r.IsBool());
-}
-
-TEST_F(IR_RegisterTest, var) {
- std::stringstream str;
-
- Symbol s;
- Register r(s, 2);
- EXPECT_EQ(2u, r.AsVarData().id);
- EXPECT_EQ(s, r.AsVarData().sym);
-
- str << r;
- EXPECT_EQ("%v2", str.str());
- str.str("");
-
- r = Register(s, 4);
- EXPECT_EQ(4u, r.AsVarData().id);
- EXPECT_EQ(s, r.AsVarData().sym);
-
- str << r;
- EXPECT_EQ("%v4", str.str());
-
- EXPECT_FALSE(r.IsF32());
- EXPECT_FALSE(r.IsF16());
- EXPECT_FALSE(r.IsI32());
- EXPECT_FALSE(r.IsU32());
- EXPECT_FALSE(r.IsTemp());
- EXPECT_TRUE(r.IsVar());
- EXPECT_FALSE(r.IsBool());
-}
-
-TEST_F(IR_RegisterTest, uninitialized) {
- Register r;
-
- EXPECT_FALSE(r.IsF32());
- EXPECT_FALSE(r.IsF16());
- EXPECT_FALSE(r.IsI32());
- EXPECT_FALSE(r.IsU32());
- EXPECT_FALSE(r.IsTemp());
- EXPECT_FALSE(r.IsVar());
- EXPECT_FALSE(r.IsBool());
-}
-
-} // namespace
-} // namespace tint::ir
diff --git a/src/tint/ir/switch.h b/src/tint/ir/switch.h
index 73284cf..e526fe8 100644
--- a/src/tint/ir/switch.h
+++ b/src/tint/ir/switch.h
@@ -17,7 +17,7 @@
#include "src/tint/ir/block.h"
#include "src/tint/ir/flow_node.h"
-#include "src/tint/ir/register.h"
+#include "src/tint/ir/value.h"
// Forward declarations
namespace tint::ast {
@@ -52,8 +52,8 @@
/// The switch case statements
utils::Vector<Case, 4> cases;
- /// Register holding the condition result
- Register condition;
+ /// Value holding the condition result
+ Value condition;
};
} // namespace tint::ir
diff --git a/src/tint/ir/value.cc b/src/tint/ir/value.cc
new file mode 100644
index 0000000..bd45a98
--- /dev/null
+++ b/src/tint/ir/value.cc
@@ -0,0 +1,76 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/ir/value.h"
+
+namespace tint::ir {
+
+Value::Value() : kind_(Kind::kUninitialized), data_(Id(0)) {}
+
+Value::Value(Id id) : kind_(Kind::kTemp), data_(id) {}
+
+Value::Value(f32 f) : kind_(Kind::kF32), data_(f) {}
+
+Value::Value(f16 f) : kind_(Kind::kF16), data_(f) {}
+
+Value::Value(u32 u) : kind_(Kind::kU32), data_(u) {}
+
+Value::Value(i32 i) : kind_(Kind::kI32), data_(i) {}
+
+Value::Value(bool b) : kind_(Kind::kBool), data_(b) {}
+
+Value::Value(Symbol s, Id id) : kind_(Kind::kVar), data_(VarData{s, id}) {}
+
+Value::~Value() = default;
+
+Value::Value(const Value& o) = default;
+
+Value::Value(Value&& o) = default;
+
+Value& Value::operator=(const Value& o) = default;
+
+Value& Value::operator=(Value&& o) = default;
+
+std::ostream& operator<<(std::ostream& out, const Value& r) {
+ switch (r.GetKind()) {
+ case Value::Kind::kTemp:
+ out << "%" << std::to_string(r.AsId());
+ break;
+ case Value::Kind::kF32:
+ out << std::to_string(r.AsF32().value);
+ break;
+ case Value::Kind::kF16:
+ out << std::to_string(r.AsF16().value);
+ break;
+ case Value::Kind::kI32:
+ out << std::to_string(r.AsI32().value);
+ break;
+ case Value::Kind::kU32:
+ out << std::to_string(r.AsU32().value);
+ break;
+ // TODO(dsinclair): Emit the symbol instead of v
+ case Value::Kind::kVar:
+ out << "%v" << std::to_string(r.AsVarData().id);
+ break;
+ case Value::Kind::kBool:
+ out << (r.AsBool() ? "true" : "false");
+ break;
+ case Value::Kind::kUninitialized:
+ out << "unknown value";
+ break;
+ }
+ return out;
+}
+
+} // namespace tint::ir
diff --git a/src/tint/ir/value.h b/src/tint/ir/value.h
new file mode 100644
index 0000000..7c9f8b5
--- /dev/null
+++ b/src/tint/ir/value.h
@@ -0,0 +1,169 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_VALUE_H_
+#define SRC_TINT_IR_VALUE_H_
+
+#include <ostream>
+#include <variant>
+
+#include "src/tint/number.h"
+#include "src/tint/symbol.h"
+
+namespace tint::ir {
+
+/// Value in the IR. The value can be one of several types these include, but aren't limited
+/// to, `f32`, `u32`, `temp`, `var`. The type of the value determines the type of data stored
+/// in the value.
+class Value {
+ public:
+ /// A value id.
+ using Id = uint32_t;
+
+ /// The type of the value
+ enum class Kind {
+ /// A uninitialized value
+ kUninitialized,
+ /// A temporary allocated value
+ kTemp,
+ /// A f32 value
+ kF32,
+ /// A f16 value
+ kF16,
+ /// An i32 value
+ kI32,
+ /// A u32 value
+ kU32,
+ /// A variable value
+ kVar,
+ /// A boolean value
+ kBool,
+ };
+
+ /// Stores data for a given variable. There will be multiple `VarData` entries for a given `id`.
+ /// The `id` acts like a generation number (although they aren't sequential, they are
+ /// increasing). As the variable is stored too a new value will be created and the the `id`
+ /// will be incremented.
+ struct VarData {
+ /// The symbol for the variable
+ Symbol sym;
+ /// The id for the variable.
+ Id id;
+ // TODO(dsinclair): Should var type data be stored here along side the variable info?
+ };
+
+ /// Constructor
+ /// Creates a uninitialized value
+ Value();
+
+ /// Constructor
+ /// @param id the id for the value
+ explicit Value(Id id);
+
+ /// Constructor
+ /// @param s the symbol for the value
+ /// @param id the id for the value
+ Value(Symbol s, Id id);
+
+ /// Constructor
+ /// @param b the `bool` value to store in the value
+ explicit Value(bool b);
+
+ /// Constructor
+ /// @param f the `f32` value to store in the value
+ explicit Value(f32 f);
+
+ /// Constructor
+ /// @param f the `f16` value to store in the value
+ explicit Value(f16 f);
+
+ /// Constructor
+ /// @param u the `u32` value to store in the value
+ explicit Value(u32 u);
+
+ /// Constructor
+ /// @param i the `i32` value to store in the value
+ explicit Value(i32 i);
+
+ /// Destructor
+ ~Value();
+
+ /// Copy constructor
+ /// @param o the value to copy from
+ Value(const Value& o);
+ /// Move constructor
+ /// @param o the value to move from
+ Value(Value&& o);
+
+ /// Copy assign
+ /// @param o the value to copy from
+ /// @returns this
+ Value& operator=(const Value& o);
+ /// Move assign
+ /// @param o the value to move from
+ /// @returns this
+ Value& operator=(Value&& o);
+
+ /// @returns true if this is a temporary value
+ bool IsTemp() const { return kind_ == Kind::kTemp; }
+ /// @returns true if this is a f32 value
+ bool IsF32() const { return kind_ == Kind::kF32; }
+ /// @returns true if this is a f16 value
+ bool IsF16() const { return kind_ == Kind::kF16; }
+ /// @returns true if this is an i32 value
+ bool IsI32() const { return kind_ == Kind::kI32; }
+ /// @returns true if this is a u32 value
+ bool IsU32() const { return kind_ == Kind::kU32; }
+ /// @returns true if this is a var value
+ bool IsVar() const { return kind_ == Kind::kVar; }
+ /// @returns true if this is a bool value
+ bool IsBool() const { return kind_ == Kind::kBool; }
+
+ /// @returns the kind of value
+ Kind GetKind() const { return kind_; }
+
+ /// @returns the value data as a `f32`.
+ /// @note, must only be called if `IsF32()` is true
+ f32 AsF32() const { return std::get<f32>(data_); }
+ /// @returns the value data as a `f16`.
+ /// @note, must only be called if `IsF16()` is true
+ f16 AsF16() const { return std::get<f16>(data_); }
+ /// @returns the value data as an `i32`.
+ /// @note, must only be called if `IsI32()` is true
+ i32 AsI32() const { return std::get<i32>(data_); }
+ /// @returns the value data as a `u32`.
+ /// @note, must only be called if `IsU32()` is true
+ u32 AsU32() const { return std::get<u32>(data_); }
+ /// @returns the value data as an `Id`.
+ /// @note, must only be called if `IsTemp()` is true
+ Id AsId() const { return std::get<Id>(data_); }
+ /// @returns the value data as a `VarData` structure.
+ /// @note, must only be called if `IsVar()` is true
+ VarData AsVarData() const { return std::get<VarData>(data_); }
+ /// @returns the value data as a `bool`.
+ /// @note, must only be called if `IsBool()` is true
+ bool AsBool() const { return std::get<bool>(data_); }
+
+ private:
+ /// The type of data stored in this value
+ Kind kind_;
+ /// The data stored in the value
+ std::variant<Id, f32, f16, u32, i32, VarData, bool> data_;
+};
+
+std::ostream& operator<<(std::ostream& out, const Value& r);
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_VALUE_H_
diff --git a/src/tint/ir/value_test.cc b/src/tint/ir/value_test.cc
new file mode 100644
index 0000000..77ee3e4
--- /dev/null
+++ b/src/tint/ir/value_test.cc
@@ -0,0 +1,183 @@
+// Copyright 2022 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <sstream>
+
+#include "src/tint/ir/test_helper.h"
+#include "src/tint/ir/value.h"
+
+namespace tint::ir {
+namespace {
+
+using namespace tint::number_suffixes; // NOLINT
+
+using IR_ValueTest = TestHelper;
+
+TEST_F(IR_ValueTest, f32) {
+ std::stringstream str;
+
+ Value val(1.2_f);
+ EXPECT_EQ(1.2_f, val.AsF32());
+
+ str << val;
+ EXPECT_EQ("1.200000", str.str());
+
+ EXPECT_TRUE(val.IsF32());
+ EXPECT_FALSE(val.IsF16());
+ EXPECT_FALSE(val.IsI32());
+ EXPECT_FALSE(val.IsU32());
+ EXPECT_FALSE(val.IsTemp());
+ EXPECT_FALSE(val.IsVar());
+ EXPECT_FALSE(val.IsBool());
+}
+
+TEST_F(IR_ValueTest, f16) {
+ std::stringstream str;
+
+ Value val(1.1_h);
+ EXPECT_EQ(1.1_h, val.AsF16());
+
+ str << val;
+ EXPECT_EQ("1.099609", str.str());
+
+ EXPECT_FALSE(val.IsF32());
+ EXPECT_TRUE(val.IsF16());
+ EXPECT_FALSE(val.IsI32());
+ EXPECT_FALSE(val.IsU32());
+ EXPECT_FALSE(val.IsTemp());
+ EXPECT_FALSE(val.IsVar());
+ EXPECT_FALSE(val.IsBool());
+}
+
+TEST_F(IR_ValueTest, i32) {
+ std::stringstream str;
+
+ Value val(1_i);
+ EXPECT_EQ(1_i, val.AsI32());
+
+ str << val;
+ EXPECT_EQ("1", str.str());
+
+ EXPECT_FALSE(val.IsF32());
+ EXPECT_FALSE(val.IsF16());
+ EXPECT_TRUE(val.IsI32());
+ EXPECT_FALSE(val.IsU32());
+ EXPECT_FALSE(val.IsTemp());
+ EXPECT_FALSE(val.IsVar());
+ EXPECT_FALSE(val.IsBool());
+}
+
+TEST_F(IR_ValueTest, u32) {
+ std::stringstream str;
+
+ Value val(2_u);
+ EXPECT_EQ(2_u, val.AsU32());
+
+ str << val;
+ EXPECT_EQ("2", str.str());
+
+ EXPECT_FALSE(val.IsF32());
+ EXPECT_FALSE(val.IsF16());
+ EXPECT_FALSE(val.IsI32());
+ EXPECT_TRUE(val.IsU32());
+ EXPECT_FALSE(val.IsTemp());
+ EXPECT_FALSE(val.IsVar());
+ EXPECT_FALSE(val.IsBool());
+}
+
+TEST_F(IR_ValueTest, id) {
+ std::stringstream str;
+
+ Value val(Value::Id(4));
+ EXPECT_EQ(4u, val.AsId());
+
+ str << val;
+ EXPECT_EQ("%4", str.str());
+
+ EXPECT_FALSE(val.IsF32());
+ EXPECT_FALSE(val.IsF16());
+ EXPECT_FALSE(val.IsI32());
+ EXPECT_FALSE(val.IsU32());
+ EXPECT_TRUE(val.IsTemp());
+ EXPECT_FALSE(val.IsVar());
+ EXPECT_FALSE(val.IsBool());
+}
+
+TEST_F(IR_ValueTest, bool) {
+ std::stringstream str;
+
+ Value val(false);
+ EXPECT_FALSE(val.AsBool());
+
+ str << val;
+ EXPECT_EQ("false", str.str());
+
+ str.str("");
+ val = Value(true);
+ EXPECT_TRUE(val.AsBool());
+
+ str << val;
+ EXPECT_EQ("true", str.str());
+
+ EXPECT_FALSE(val.IsF32());
+ EXPECT_FALSE(val.IsF16());
+ EXPECT_FALSE(val.IsI32());
+ EXPECT_FALSE(val.IsU32());
+ EXPECT_FALSE(val.IsTemp());
+ EXPECT_FALSE(val.IsVar());
+ EXPECT_TRUE(val.IsBool());
+}
+
+TEST_F(IR_ValueTest, var) {
+ std::stringstream str;
+
+ Symbol s;
+ Value val(s, 2);
+ EXPECT_EQ(2u, val.AsVarData().id);
+ EXPECT_EQ(s, val.AsVarData().sym);
+
+ str << val;
+ EXPECT_EQ("%v2", str.str());
+ str.str("");
+
+ val = Value(s, 4);
+ EXPECT_EQ(4u, val.AsVarData().id);
+ EXPECT_EQ(s, val.AsVarData().sym);
+
+ str << val;
+ EXPECT_EQ("%v4", str.str());
+
+ EXPECT_FALSE(val.IsF32());
+ EXPECT_FALSE(val.IsF16());
+ EXPECT_FALSE(val.IsI32());
+ EXPECT_FALSE(val.IsU32());
+ EXPECT_FALSE(val.IsTemp());
+ EXPECT_TRUE(val.IsVar());
+ EXPECT_FALSE(val.IsBool());
+}
+
+TEST_F(IR_ValueTest, uninitialized) {
+ Value val;
+
+ EXPECT_FALSE(val.IsF32());
+ EXPECT_FALSE(val.IsF16());
+ EXPECT_FALSE(val.IsI32());
+ EXPECT_FALSE(val.IsU32());
+ EXPECT_FALSE(val.IsTemp());
+ EXPECT_FALSE(val.IsVar());
+ EXPECT_FALSE(val.IsBool());
+}
+
+} // namespace
+} // namespace tint::ir