[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>
This commit is contained in:
dan sinclair 2022-11-28 22:02:39 +00:00 committed by Dawn LUCI CQ
parent 3728a505d6
commit 62a07738c8
19 changed files with 985 additions and 987 deletions

View File

@ -666,18 +666,18 @@ if(${TINT_BUILD_IR})
ir/function.h ir/function.h
ir/if.cc ir/if.cc
ir/if.h ir/if.h
ir/instruction.cc
ir/instruction.h
ir/loop.cc ir/loop.cc
ir/loop.h ir/loop.h
ir/module.cc ir/module.cc
ir/module.h ir/module.h
ir/op.cc
ir/op.h
ir/register.cc
ir/register.h
ir/switch.cc ir/switch.cc
ir/switch.h ir/switch.h
ir/terminator.cc ir/terminator.cc
ir/terminator.h ir/terminator.h
ir/value.cc
ir/value.h
) )
endif() endif()
@ -1341,9 +1341,9 @@ if(TINT_BUILD_TESTS)
if (${TINT_BUILD_IR}) if (${TINT_BUILD_IR})
list(APPEND TINT_TEST_SRCS list(APPEND TINT_TEST_SRCS
ir/builder_impl_test.cc ir/builder_impl_test.cc
ir/op_test.cc ir/instruction_test.cc
ir/register_test.cc
ir/test_helper.h ir/test_helper.h
ir/value_test.cc
) )
endif() endif()

View File

@ -16,7 +16,7 @@
#define SRC_TINT_IR_BLOCK_H_ #define SRC_TINT_IR_BLOCK_H_
#include "src/tint/ir/flow_node.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" #include "src/tint/utils/vector.h"
namespace tint::ir { namespace tint::ir {
@ -33,8 +33,8 @@ class Block : public Castable<Block, FlowNode> {
/// The node this block branches too. /// The node this block branches too.
const FlowNode* branch_target = nullptr; const FlowNode* branch_target = nullptr;
/// The operations in the block /// The instructions in the block
utils::Vector<Op, 16> ops; utils::Vector<Instruction, 16> instructions;
}; };
} // namespace tint::ir } // namespace tint::ir

View File

@ -93,84 +93,84 @@ void Builder::Branch(Block* from, FlowNode* to) {
to->inbound_branches.Push(from); to->inbound_branches.Push(from);
} }
Register::Id Builder::AllocateRegister() { Value::Id Builder::AllocateValue() {
return next_register_id++; return next_value_id++;
} }
Op Builder::CreateOp(Op::Kind kind, Register lhs, Register rhs) { Instruction Builder::CreateInstruction(Instruction::Kind kind, Value lhs, Value rhs) {
return Op(kind, Register(AllocateRegister()), lhs, rhs); return Instruction(kind, Value(AllocateValue()), lhs, rhs);
} }
Op Builder::And(Register lhs, Register rhs) { Instruction Builder::And(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kAnd, lhs, rhs); return CreateInstruction(Instruction::Kind::kAnd, lhs, rhs);
} }
Op Builder::Or(Register lhs, Register rhs) { Instruction Builder::Or(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kOr, lhs, rhs); return CreateInstruction(Instruction::Kind::kOr, lhs, rhs);
} }
Op Builder::Xor(Register lhs, Register rhs) { Instruction Builder::Xor(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kXor, lhs, rhs); return CreateInstruction(Instruction::Kind::kXor, lhs, rhs);
} }
Op Builder::LogicalAnd(Register lhs, Register rhs) { Instruction Builder::LogicalAnd(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kLogicalAnd, lhs, rhs); return CreateInstruction(Instruction::Kind::kLogicalAnd, lhs, rhs);
} }
Op Builder::LogicalOr(Register lhs, Register rhs) { Instruction Builder::LogicalOr(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kLogicalOr, lhs, rhs); return CreateInstruction(Instruction::Kind::kLogicalOr, lhs, rhs);
} }
Op Builder::Equal(Register lhs, Register rhs) { Instruction Builder::Equal(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kEqual, lhs, rhs); return CreateInstruction(Instruction::Kind::kEqual, lhs, rhs);
} }
Op Builder::NotEqual(Register lhs, Register rhs) { Instruction Builder::NotEqual(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kNotEqual, lhs, rhs); return CreateInstruction(Instruction::Kind::kNotEqual, lhs, rhs);
} }
Op Builder::LessThan(Register lhs, Register rhs) { Instruction Builder::LessThan(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kLessThan, lhs, rhs); return CreateInstruction(Instruction::Kind::kLessThan, lhs, rhs);
} }
Op Builder::GreaterThan(Register lhs, Register rhs) { Instruction Builder::GreaterThan(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kGreaterThan, lhs, rhs); return CreateInstruction(Instruction::Kind::kGreaterThan, lhs, rhs);
} }
Op Builder::LessThanEqual(Register lhs, Register rhs) { Instruction Builder::LessThanEqual(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kLessThanEqual, lhs, rhs); return CreateInstruction(Instruction::Kind::kLessThanEqual, lhs, rhs);
} }
Op Builder::GreaterThanEqual(Register lhs, Register rhs) { Instruction Builder::GreaterThanEqual(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kGreaterThanEqual, lhs, rhs); return CreateInstruction(Instruction::Kind::kGreaterThanEqual, lhs, rhs);
} }
Op Builder::ShiftLeft(Register lhs, Register rhs) { Instruction Builder::ShiftLeft(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kShiftLeft, lhs, rhs); return CreateInstruction(Instruction::Kind::kShiftLeft, lhs, rhs);
} }
Op Builder::ShiftRight(Register lhs, Register rhs) { Instruction Builder::ShiftRight(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kShiftRight, lhs, rhs); return CreateInstruction(Instruction::Kind::kShiftRight, lhs, rhs);
} }
Op Builder::Add(Register lhs, Register rhs) { Instruction Builder::Add(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kAdd, lhs, rhs); return CreateInstruction(Instruction::Kind::kAdd, lhs, rhs);
} }
Op Builder::Subtract(Register lhs, Register rhs) { Instruction Builder::Subtract(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kSubtract, lhs, rhs); return CreateInstruction(Instruction::Kind::kSubtract, lhs, rhs);
} }
Op Builder::Multiply(Register lhs, Register rhs) { Instruction Builder::Multiply(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kMultiply, lhs, rhs); return CreateInstruction(Instruction::Kind::kMultiply, lhs, rhs);
} }
Op Builder::Divide(Register lhs, Register rhs) { Instruction Builder::Divide(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kDivide, lhs, rhs); return CreateInstruction(Instruction::Kind::kDivide, lhs, rhs);
} }
Op Builder::Modulo(Register lhs, Register rhs) { Instruction Builder::Modulo(Value lhs, Value rhs) {
return CreateOp(Op::Kind::kModulo, lhs, rhs); return CreateInstruction(Instruction::Kind::kModulo, lhs, rhs);
} }
} // namespace tint::ir } // namespace tint::ir

View File

@ -17,12 +17,12 @@
#include "src/tint/ir/function.h" #include "src/tint/ir/function.h"
#include "src/tint/ir/if.h" #include "src/tint/ir/if.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/loop.h" #include "src/tint/ir/loop.h"
#include "src/tint/ir/module.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/switch.h"
#include "src/tint/ir/terminator.h" #include "src/tint/ir/terminator.h"
#include "src/tint/ir/value.h"
// Forward Declarations // Forward Declarations
namespace tint { namespace tint {
@ -88,124 +88,124 @@ class Builder {
/// @param lhs the left-hand-side of the operation /// @param lhs the left-hand-side of the operation
/// @param rhs the right-hand-side of the operation /// @param rhs the right-hand-side of the operation
/// @returns 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 /// Creates an And operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op And(Register lhs, Register rhs); Instruction And(Value lhs, Value rhs);
/// Creates an Or operation /// Creates an Or operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op Or(Register lhs, Register rhs); Instruction Or(Value lhs, Value rhs);
/// Creates an Xor operation /// Creates an Xor operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op Xor(Register lhs, Register rhs); Instruction Xor(Value lhs, Value rhs);
/// Creates an LogicalAnd operation /// Creates an LogicalAnd operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op LogicalAnd(Register lhs, Register rhs); Instruction LogicalAnd(Value lhs, Value rhs);
/// Creates an LogicalOr operation /// Creates an LogicalOr operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op LogicalOr(Register lhs, Register rhs); Instruction LogicalOr(Value lhs, Value rhs);
/// Creates an Equal operation /// Creates an Equal operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op Equal(Register lhs, Register rhs); Instruction Equal(Value lhs, Value rhs);
/// Creates an NotEqual operation /// Creates an NotEqual operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op NotEqual(Register lhs, Register rhs); Instruction NotEqual(Value lhs, Value rhs);
/// Creates an LessThan operation /// Creates an LessThan operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op LessThan(Register lhs, Register rhs); Instruction LessThan(Value lhs, Value rhs);
/// Creates an GreaterThan operation /// Creates an GreaterThan operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op GreaterThan(Register lhs, Register rhs); Instruction GreaterThan(Value lhs, Value rhs);
/// Creates an LessThanEqual operation /// Creates an LessThanEqual operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op LessThanEqual(Register lhs, Register rhs); Instruction LessThanEqual(Value lhs, Value rhs);
/// Creates an GreaterThanEqual operation /// Creates an GreaterThanEqual operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op GreaterThanEqual(Register lhs, Register rhs); Instruction GreaterThanEqual(Value lhs, Value rhs);
/// Creates an ShiftLeft operation /// Creates an ShiftLeft operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op ShiftLeft(Register lhs, Register rhs); Instruction ShiftLeft(Value lhs, Value rhs);
/// Creates an ShiftRight operation /// Creates an ShiftRight operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op ShiftRight(Register lhs, Register rhs); Instruction ShiftRight(Value lhs, Value rhs);
/// Creates an Add operation /// Creates an Add operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op Add(Register lhs, Register rhs); Instruction Add(Value lhs, Value rhs);
/// Creates an Subtract operation /// Creates an Subtract operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op Subtract(Register lhs, Register rhs); Instruction Subtract(Value lhs, Value rhs);
/// Creates an Multiply operation /// Creates an Multiply operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op Multiply(Register lhs, Register rhs); Instruction Multiply(Value lhs, Value rhs);
/// Creates an Divide operation /// Creates an Divide operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op Divide(Register lhs, Register rhs); Instruction Divide(Value lhs, Value rhs);
/// Creates an Modulo operation /// Creates an Modulo operation
/// @param lhs the lhs of the add /// @param lhs the lhs of the add
/// @param rhs the rhs of the add /// @param rhs the rhs of the add
/// @returns the operation /// @returns the operation
Op Modulo(Register lhs, Register rhs); Instruction Modulo(Value lhs, Value rhs);
/// @returns a unique register id /// @returns a unique Value id
Register::Id AllocateRegister(); Value::Id AllocateValue();
/// The IR module. /// The IR module.
Module ir; Module ir;
/// The next register number to allocate /// The next Value number to allocate
Register::Id next_register_id = 1; Value::Id next_value_id = 1;
}; };
} // namespace tint::ir } // namespace tint::ir

View File

@ -516,7 +516,7 @@ bool BuilderImpl::EmitBreakIf(const ast::BreakIfStatement* stmt) {
return true; return true;
} }
utils::Result<Register> BuilderImpl::EmitExpression(const ast::Expression* expr) { utils::Result<Value> BuilderImpl::EmitExpression(const ast::Expression* expr) {
return tint::Switch( return tint::Switch(
expr, expr,
// [&](const ast::IndexAccessorExpression* a) { return EmitIndexAccessor(a); }, // [&](const ast::IndexAccessorExpression* a) { return EmitIndexAccessor(a); },
@ -551,7 +551,7 @@ bool BuilderImpl::EmitVariable(const ast::Variable* var) {
}); });
} }
utils::Result<Register> BuilderImpl::EmitBinary(const ast::BinaryExpression* expr) { utils::Result<Value> BuilderImpl::EmitBinary(const ast::BinaryExpression* expr) {
auto lhs = EmitExpression(expr->lhs); auto lhs = EmitExpression(expr->lhs);
if (!lhs) { if (!lhs) {
return utils::Failure; return utils::Failure;
@ -562,89 +562,87 @@ utils::Result<Register> BuilderImpl::EmitBinary(const ast::BinaryExpression* exp
return utils::Failure; return utils::Failure;
} }
Op op; Instruction instr;
switch (expr->op) { switch (expr->op) {
case ast::BinaryOp::kAnd: case ast::BinaryOp::kAnd:
op = builder.And(lhs.Get(), rhs.Get()); instr = builder.And(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kOr: case ast::BinaryOp::kOr:
op = builder.Or(lhs.Get(), rhs.Get()); instr = builder.Or(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kXor: case ast::BinaryOp::kXor:
op = builder.Xor(lhs.Get(), rhs.Get()); instr = builder.Xor(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kLogicalAnd: case ast::BinaryOp::kLogicalAnd:
op = builder.LogicalAnd(lhs.Get(), rhs.Get()); instr = builder.LogicalAnd(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kLogicalOr: case ast::BinaryOp::kLogicalOr:
op = builder.LogicalOr(lhs.Get(), rhs.Get()); instr = builder.LogicalOr(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kEqual: case ast::BinaryOp::kEqual:
op = builder.Equal(lhs.Get(), rhs.Get()); instr = builder.Equal(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kNotEqual: case ast::BinaryOp::kNotEqual:
op = builder.NotEqual(lhs.Get(), rhs.Get()); instr = builder.NotEqual(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kLessThan: case ast::BinaryOp::kLessThan:
op = builder.LessThan(lhs.Get(), rhs.Get()); instr = builder.LessThan(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kGreaterThan: case ast::BinaryOp::kGreaterThan:
op = builder.GreaterThan(lhs.Get(), rhs.Get()); instr = builder.GreaterThan(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kLessThanEqual: case ast::BinaryOp::kLessThanEqual:
op = builder.LessThanEqual(lhs.Get(), rhs.Get()); instr = builder.LessThanEqual(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kGreaterThanEqual: case ast::BinaryOp::kGreaterThanEqual:
op = builder.GreaterThanEqual(lhs.Get(), rhs.Get()); instr = builder.GreaterThanEqual(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kShiftLeft: case ast::BinaryOp::kShiftLeft:
op = builder.ShiftLeft(lhs.Get(), rhs.Get()); instr = builder.ShiftLeft(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kShiftRight: case ast::BinaryOp::kShiftRight:
op = builder.ShiftRight(lhs.Get(), rhs.Get()); instr = builder.ShiftRight(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kAdd: case ast::BinaryOp::kAdd:
op = builder.Add(lhs.Get(), rhs.Get()); instr = builder.Add(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kSubtract: case ast::BinaryOp::kSubtract:
op = builder.Subtract(lhs.Get(), rhs.Get()); instr = builder.Subtract(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kMultiply: case ast::BinaryOp::kMultiply:
op = builder.Multiply(lhs.Get(), rhs.Get()); instr = builder.Multiply(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kDivide: case ast::BinaryOp::kDivide:
op = builder.Divide(lhs.Get(), rhs.Get()); instr = builder.Divide(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kModulo: case ast::BinaryOp::kModulo:
op = builder.Modulo(lhs.Get(), rhs.Get()); instr = builder.Modulo(lhs.Get(), rhs.Get());
break; break;
case ast::BinaryOp::kNone: case ast::BinaryOp::kNone:
TINT_ICE(IR, diagnostics_) << "missing binary operand type"; TINT_ICE(IR, diagnostics_) << "missing binary operand type";
return utils::Failure; return utils::Failure;
} }
auto result = op.Result(); auto result = instr.Result();
current_flow_block->ops.Push(op); current_flow_block->instructions.Push(instr);
return result; return result;
} }
utils::Result<Register> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) { utils::Result<Value> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
return tint::Switch( // return tint::Switch( //
lit, lit,
[&](const ast::BoolLiteralExpression* l) { [&](const ast::BoolLiteralExpression* l) { return utils::Result<Value>{Value(l->value)}; },
return utils::Result<Register>{Register(l->value)};
},
[&](const ast::FloatLiteralExpression* l) { [&](const ast::FloatLiteralExpression* l) {
if (l->suffix == ast::FloatLiteralExpression::Suffix::kF) { 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) { [&](const ast::IntLiteralExpression* l) {
if (l->suffix == ast::IntLiteralExpression::Suffix::kI) { 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) { [&](Default) {
diagnostics_.add_warning(tint::diag::System::IR, diagnostics_.add_warning(tint::diag::System::IR,

View File

@ -23,7 +23,7 @@
#include "src/tint/ir/builder.h" #include "src/tint/ir/builder.h"
#include "src/tint/ir/flow_node.h" #include "src/tint/ir/flow_node.h"
#include "src/tint/ir/module.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" #include "src/tint/utils/result.h"
// Forward Declarations // Forward Declarations
@ -140,7 +140,7 @@ class BuilderImpl {
/// Emits an expression /// Emits an expression
/// @param expr the expression to emit /// @param expr the expression to emit
/// @returns true if successful, false otherwise /// @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 /// Emits a variable
/// @param var the variable to emit /// @param var the variable to emit
@ -149,13 +149,13 @@ class BuilderImpl {
/// Emits a binary expression /// Emits a binary expression
/// @param expr the binary expression /// @param expr the binary expression
/// @returns the register storing the result if successful, utils::Failure otherwise /// @returns the value storing the result if successful, utils::Failure otherwise
utils::Result<Register> EmitBinary(const ast::BinaryExpression* expr); utils::Result<Value> EmitBinary(const ast::BinaryExpression* expr);
/// Emits a literal expression /// Emits a literal expression
/// @param lit the literal to emit /// @param lit the literal to emit
/// @returns true if successful, false otherwise /// @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 /// Emits a type
/// @param ty the type to emit /// @param ty the type to emit

View File

@ -101,9 +101,9 @@ TEST_F(IR_BuilderImplTest, IfStatement) {
EXPECT_EQ(flow->merge_target->branch_target, func->end_target); EXPECT_EQ(flow->merge_target->branch_target, func->end_target);
// Check condition // Check condition
auto op = flow->condition; auto instr = flow->condition;
ASSERT_TRUE(op.IsBool()); ASSERT_TRUE(instr.IsBool());
EXPECT_TRUE(op.AsBool()); EXPECT_TRUE(instr.AsBool());
} }
TEST_F(IR_BuilderImplTest, IfStatement_TrueReturns) { TEST_F(IR_BuilderImplTest, IfStatement_TrueReturns) {
@ -502,9 +502,9 @@ TEST_F(IR_BuilderImplTest, Loop_WithReturn) {
EXPECT_EQ(loop_flow->merge_target->branch_target, nullptr); EXPECT_EQ(loop_flow->merge_target->branch_target, nullptr);
// Check condition // Check condition
auto op = if_flow->condition; auto instr = if_flow->condition;
ASSERT_TRUE(op.IsBool()); ASSERT_TRUE(instr.IsBool());
EXPECT_TRUE(op.AsBool()); EXPECT_TRUE(instr.AsBool());
} }
TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn) { TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn) {
@ -947,9 +947,9 @@ TEST_F(IR_BuilderImplTest, While) {
EXPECT_EQ(flow->merge_target->branch_target, func->end_target); EXPECT_EQ(flow->merge_target->branch_target, func->end_target);
// Check condition // Check condition
auto op = if_flow->condition; auto instr = if_flow->condition;
ASSERT_TRUE(op.IsBool()); ASSERT_TRUE(instr.IsBool());
EXPECT_FALSE(op.AsBool()); EXPECT_FALSE(instr.AsBool());
} }
TEST_F(IR_BuilderImplTest, While_Return) { TEST_F(IR_BuilderImplTest, While_Return) {
@ -1071,9 +1071,9 @@ TEST_F(IR_BuilderImplTest, DISABLED_For) {
EXPECT_EQ(flow->merge_target->branch_target, func->end_target); EXPECT_EQ(flow->merge_target->branch_target, func->end_target);
// Check condition // Check condition
auto op = if_flow->condition; auto instr = if_flow->condition;
ASSERT_TRUE(op.IsBool()); ASSERT_TRUE(instr.IsBool());
EXPECT_FALSE(op.AsBool()); EXPECT_FALSE(instr.AsBool());
} }
TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) { TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) {
@ -1171,9 +1171,9 @@ TEST_F(IR_BuilderImplTest, Switch) {
EXPECT_EQ(flow->merge_target->branch_target, func->end_target); EXPECT_EQ(flow->merge_target->branch_target, func->end_target);
// Check condition // Check condition
auto op = flow->condition; auto instr = flow->condition;
ASSERT_TRUE(op.IsI32()); ASSERT_TRUE(instr.IsI32());
EXPECT_EQ(1_i, op.AsI32()); EXPECT_EQ(1_i, instr.AsI32());
} }
TEST_F(IR_BuilderImplTest, Switch_OnlyDefault) { TEST_F(IR_BuilderImplTest, Switch_OnlyDefault) {
@ -1402,7 +1402,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 + 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 + 4
)"); )");
} }
@ -1413,7 +1413,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 - 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 - 4
)"); )");
} }
@ -1424,7 +1424,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 * 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 * 4
)"); )");
} }
@ -1435,7 +1435,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 / 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 / 4
)"); )");
} }
@ -1446,7 +1446,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 % 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 % 4
)"); )");
} }
@ -1457,7 +1457,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 & 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 & 4
)"); )");
} }
@ -1468,7 +1468,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 | 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 | 4
)"); )");
} }
@ -1479,7 +1479,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 ^ 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 ^ 4
)"); )");
} }
@ -1490,7 +1490,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 && 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 && 4
)"); )");
} }
@ -1501,7 +1501,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 || 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 || 4
)"); )");
} }
@ -1512,7 +1512,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Eqaul) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 == 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 == 4
)"); )");
} }
@ -1523,7 +1523,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 != 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 != 4
)"); )");
} }
@ -1534,7 +1534,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 < 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 < 4
)"); )");
} }
@ -1545,7 +1545,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 > 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 > 4
)"); )");
} }
@ -1556,7 +1556,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 <= 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 <= 4
)"); )");
} }
@ -1567,7 +1567,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >= 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 >= 4
)"); )");
} }
@ -1578,7 +1578,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 << 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 << 4
)"); )");
} }
@ -1589,7 +1589,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >> 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 >> 4
)"); )");
} }
@ -1601,7 +1601,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) {
ASSERT_TRUE(r); ASSERT_TRUE(r);
Disassembler d; Disassembler d;
d.EmitBlockOps(b.current_flow_block); d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >> 4 EXPECT_EQ(d.AsString(), R"(%1 = 3 >> 4
%2 = %1 + 9 %2 = %1 + 9
%3 = 1 < %2 %3 = 1 < %2

View File

@ -61,9 +61,9 @@ std::ostream& Disassembler::Indent() {
return out_; return out_;
} }
void Disassembler::EmitBlockOps(const Block* b) { void Disassembler::EmitBlockInstructions(const Block* b) {
for (const auto& op : b->ops) { for (const auto& instr : b->instructions) {
out_ << op << std::endl; out_ << instr << std::endl;
} }
} }
@ -87,7 +87,7 @@ void Disassembler::Walk(const FlowNode* node) {
}, },
[&](const ir::Block* b) { [&](const ir::Block* b) {
Indent() << "Block" << std::endl; Indent() << "Block" << std::endl;
EmitBlockOps(b); EmitBlockInstructions(b);
Walk(b->branch_target); Walk(b->branch_target);
}, },
[&](const ir::Switch* s) { [&](const ir::Switch* s) {

View File

@ -36,9 +36,9 @@ class Disassembler {
/// @returns the string representation of the module /// @returns the string representation of the module
std::string Disassemble(const Module& mod); std::string Disassemble(const Module& mod);
/// Writes the block ops to the stream /// Writes the block instructions to the stream
/// @param b the block containing the ops /// @param b the block containing the instructions
void EmitBlockOps(const Block* b); void EmitBlockInstructions(const Block* b);
/// @returns the string representation /// @returns the string representation
std::string AsString() const { return out_.str(); } std::string AsString() const { return out_.str(); }

View File

@ -17,7 +17,7 @@
#include "src/tint/ast/if_statement.h" #include "src/tint/ast/if_statement.h"
#include "src/tint/ir/flow_node.h" #include "src/tint/ir/flow_node.h"
#include "src/tint/ir/register.h" #include "src/tint/ir/value.h"
// Forward declarations // Forward declarations
namespace tint::ir { namespace tint::ir {
@ -44,8 +44,8 @@ class If : public Castable<If, FlowNode> {
/// An block to reconvert the true/false barnches. The block always exists, but there maybe no /// 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`) /// branches into it. (e.g. if both branches `return`)
Block* merge_target = nullptr; Block* merge_target = nullptr;
/// Register holding the condition result /// Value holding the condition result
Register condition; Value condition;
}; };
} // namespace tint::ir } // namespace tint::ir

View File

@ -12,91 +12,91 @@
// 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/op.h" #include "src/tint/ir/instruction.h"
namespace tint::ir { namespace tint::ir {
Op::Op() {} Instruction::Instruction() {}
Op::Op(Kind kind, Register result, Register lhs, Register rhs) Instruction::Instruction(Kind kind, Value result, Value lhs, Value rhs)
: kind_(kind), result_(result), args_({lhs, rhs}) {} : kind_(kind), result_(result), args_({lhs, rhs}) {}
Op::Op(const Op&) = default; Instruction::Instruction(const Instruction&) = default;
Op::Op(Op&& o) = default; Instruction::Instruction(Instruction&& instr) = default;
Op::~Op() = default; Instruction::~Instruction() = default;
Op& Op::operator=(const Op& o) = default; Instruction& Instruction::operator=(const Instruction& instr) = default;
Op& Op::operator=(Op&& o) = default; Instruction& Instruction::operator=(Instruction&& instr) = default;
std::ostream& operator<<(std::ostream& out, const Op& op) { std::ostream& operator<<(std::ostream& out, const Instruction& instr) {
out << op.Result() << " = "; out << instr.Result() << " = ";
if (op.HasLHS()) { if (instr.HasLHS()) {
out << op.LHS(); out << instr.LHS();
} }
out << " "; out << " ";
switch (op.GetKind()) { switch (instr.GetKind()) {
case Op::Kind::kAdd: case Instruction::Kind::kAdd:
out << "+"; out << "+";
break; break;
case Op::Kind::kSubtract: case Instruction::Kind::kSubtract:
out << "-"; out << "-";
break; break;
case Op::Kind::kMultiply: case Instruction::Kind::kMultiply:
out << "*"; out << "*";
break; break;
case Op::Kind::kDivide: case Instruction::Kind::kDivide:
out << "/"; out << "/";
break; break;
case Op::Kind::kModulo: case Instruction::Kind::kModulo:
out << "%"; out << "%";
break; break;
case Op::Kind::kAnd: case Instruction::Kind::kAnd:
out << "&"; out << "&";
break; break;
case Op::Kind::kOr: case Instruction::Kind::kOr:
out << "|"; out << "|";
break; break;
case Op::Kind::kXor: case Instruction::Kind::kXor:
out << "^"; out << "^";
break; break;
case Op::Kind::kLogicalAnd: case Instruction::Kind::kLogicalAnd:
out << "&&"; out << "&&";
break; break;
case Op::Kind::kLogicalOr: case Instruction::Kind::kLogicalOr:
out << "||"; out << "||";
break; break;
case Op::Kind::kEqual: case Instruction::Kind::kEqual:
out << "=="; out << "==";
break; break;
case Op::Kind::kNotEqual: case Instruction::Kind::kNotEqual:
out << "!="; out << "!=";
break; break;
case Op::Kind::kLessThan: case Instruction::Kind::kLessThan:
out << "<"; out << "<";
break; break;
case Op::Kind::kGreaterThan: case Instruction::Kind::kGreaterThan:
out << ">"; out << ">";
break; break;
case Op::Kind::kLessThanEqual: case Instruction::Kind::kLessThanEqual:
out << "<="; out << "<=";
break; break;
case Op::Kind::kGreaterThanEqual: case Instruction::Kind::kGreaterThanEqual:
out << ">="; out << ">=";
break; break;
case Op::Kind::kShiftLeft: case Instruction::Kind::kShiftLeft:
out << "<<"; out << "<<";
break; break;
case Op::Kind::kShiftRight: case Instruction::Kind::kShiftRight:
out << ">>"; out << ">>";
break; break;
} }
if (op.HasRHS()) { if (instr.HasRHS()) {
out << " " << op.RHS(); out << " " << instr.RHS();
} }
return out; return out;

View File

@ -12,20 +12,20 @@
// 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.
#ifndef SRC_TINT_IR_OP_H_ #ifndef SRC_TINT_IR_INSTRUCTION_H_
#define SRC_TINT_IR_OP_H_ #define SRC_TINT_IR_INSTRUCTION_H_
#include <ostream> #include <ostream>
#include "src/tint/ir/register.h" #include "src/tint/ir/value.h"
#include "src/tint/utils/vector.h" #include "src/tint/utils/vector.h"
namespace tint::ir { namespace tint::ir {
/// An operation in the IR. /// An instruction in the IR.
class Op { class Instruction {
public: public:
/// The kind of operation. /// The kind of instruction.
enum class Kind { enum class Kind {
kAdd, kAdd,
kSubtract, kSubtract,
@ -52,49 +52,49 @@ class Op {
}; };
/// Constructor /// Constructor
Op(); Instruction();
/// Constructor /// Constructor
/// @param kind the kind of operation /// @param kind the kind of instruction
/// @param result the result register /// @param result the result value
/// @param lhs the lhs of the operation /// @param lhs the lhs of the instruction
/// @param rhs the rhs of the operation /// @param rhs the rhs of the instruction
Op(Kind kind, Register result, Register lhs, Register rhs); Instruction(Kind kind, Value result, Value lhs, Value rhs);
/// Copy constructor /// Copy constructor
/// @param o the op to copy from /// @param instr the instruction to copy from
Op(const Op& o); Instruction(const Instruction& instr);
/// Move constructor /// Move constructor
/// @param o the op to move from /// @param instr the instruction to move from
Op(Op&& o); Instruction(Instruction&& instr);
/// Destructor /// Destructor
~Op(); ~Instruction();
/// Copy assign /// Copy assign
/// @param o the op to copy from /// @param instr the instruction to copy from
/// @returns a reference to this /// @returns a reference to this
Op& operator=(const Op& o); Instruction& operator=(const Instruction& instr);
/// Move assign /// Move assign
/// @param o the op to move from /// @param instr the instruction to move from
/// @returns a reference to this /// @returns a reference to this
Op& operator=(Op&& o); Instruction& operator=(Instruction&& instr);
/// @returns the kind of operation /// @returns the kind of instruction
Kind GetKind() const { return kind_; } Kind GetKind() const { return kind_; }
/// @returns the result register for the operation /// @returns the result value for the instruction
const Register& Result() const { return result_; } const Value& Result() const { return result_; }
/// @returns true if the op has a LHS /// @returns true if the instruction has a LHS
bool HasLHS() const { return args_.Length() >= 1; } bool HasLHS() const { return args_.Length() >= 1; }
/// @returns the left-hand-side register for the operation /// @returns the left-hand-side value for the instruction
const Register& LHS() const { const Value& LHS() const {
TINT_ASSERT(IR, HasLHS()); TINT_ASSERT(IR, HasLHS());
return args_[0]; return args_[0];
} }
/// @returns true if the op has a RHS /// @returns true if the instruction has a RHS
bool HasRHS() const { return args_.Length() >= 2; } bool HasRHS() const { return args_.Length() >= 2; }
/// @returns the right-hand-side register for the operation /// @returns the right-hand-side value for the instruction
const Register& RHS() const { const Value& RHS() const {
TINT_ASSERT(IR, HasRHS()); TINT_ASSERT(IR, HasRHS());
return args_[1]; return args_[1];
} }
@ -102,12 +102,12 @@ class Op {
private: private:
Kind kind_; Kind kind_;
Register result_; Value result_;
utils::Vector<Register, 2> args_; utils::Vector<Value, 2> args_;
}; };
std::ostream& operator<<(std::ostream& out, const Op&); std::ostream& operator<<(std::ostream& out, const Instruction&);
} // namespace tint::ir } // namespace tint::ir
#endif // SRC_TINT_IR_OP_H_ #endif // SRC_TINT_IR_INSTRUCTION_H_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -17,7 +17,7 @@
#include "src/tint/ir/block.h" #include "src/tint/ir/block.h"
#include "src/tint/ir/flow_node.h" #include "src/tint/ir/flow_node.h"
#include "src/tint/ir/register.h" #include "src/tint/ir/value.h"
// Forward declarations // Forward declarations
namespace tint::ast { namespace tint::ast {
@ -52,8 +52,8 @@ class Switch : public Castable<Switch, FlowNode> {
/// The switch case statements /// The switch case statements
utils::Vector<Case, 4> cases; utils::Vector<Case, 4> cases;
/// Register holding the condition result /// Value holding the condition result
Register condition; Value condition;
}; };
} // namespace tint::ir } // namespace tint::ir

View File

@ -12,62 +12,62 @@
// 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/register.h" #include "src/tint/ir/value.h"
namespace tint::ir { namespace tint::ir {
Register::Register() : kind_(Kind::kUninitialized), data_(Id(0)) {} Value::Value() : kind_(Kind::kUninitialized), data_(Id(0)) {}
Register::Register(Id id) : kind_(Kind::kTemp), data_(id) {} Value::Value(Id id) : kind_(Kind::kTemp), data_(id) {}
Register::Register(f32 f) : kind_(Kind::kF32), data_(f) {} Value::Value(f32 f) : kind_(Kind::kF32), data_(f) {}
Register::Register(f16 f) : kind_(Kind::kF16), data_(f) {} Value::Value(f16 f) : kind_(Kind::kF16), data_(f) {}
Register::Register(u32 u) : kind_(Kind::kU32), data_(u) {} Value::Value(u32 u) : kind_(Kind::kU32), data_(u) {}
Register::Register(i32 i) : kind_(Kind::kI32), data_(i) {} Value::Value(i32 i) : kind_(Kind::kI32), data_(i) {}
Register::Register(bool b) : kind_(Kind::kBool), data_(b) {} Value::Value(bool b) : kind_(Kind::kBool), data_(b) {}
Register::Register(Symbol s, Id id) : kind_(Kind::kVar), data_(VarData{s, id}) {} Value::Value(Symbol s, Id id) : kind_(Kind::kVar), data_(VarData{s, id}) {}
Register::~Register() = default; Value::~Value() = default;
Register::Register(const Register& o) = default; Value::Value(const Value& o) = default;
Register::Register(Register&& o) = default; Value::Value(Value&& o) = default;
Register& Register::operator=(const Register& o) = default; Value& Value::operator=(const Value& o) = default;
Register& Register::operator=(Register&& o) = default; Value& Value::operator=(Value&& o) = default;
std::ostream& operator<<(std::ostream& out, const Register& r) { std::ostream& operator<<(std::ostream& out, const Value& r) {
switch (r.GetKind()) { switch (r.GetKind()) {
case Register::Kind::kTemp: case Value::Kind::kTemp:
out << "%" << std::to_string(r.AsId()); out << "%" << std::to_string(r.AsId());
break; break;
case Register::Kind::kF32: case Value::Kind::kF32:
out << std::to_string(r.AsF32().value); out << std::to_string(r.AsF32().value);
break; break;
case Register::Kind::kF16: case Value::Kind::kF16:
out << std::to_string(r.AsF16().value); out << std::to_string(r.AsF16().value);
break; break;
case Register::Kind::kI32: case Value::Kind::kI32:
out << std::to_string(r.AsI32().value); out << std::to_string(r.AsI32().value);
break; break;
case Register::Kind::kU32: case Value::Kind::kU32:
out << std::to_string(r.AsU32().value); out << std::to_string(r.AsU32().value);
break; break;
// TODO(dsinclair): Emit the symbol instead of v // TODO(dsinclair): Emit the symbol instead of v
case Register::Kind::kVar: case Value::Kind::kVar:
out << "%v" << std::to_string(r.AsVarData().id); out << "%v" << std::to_string(r.AsVarData().id);
break; break;
case Register::Kind::kBool: case Value::Kind::kBool:
out << (r.AsBool() ? "true" : "false"); out << (r.AsBool() ? "true" : "false");
break; break;
case Register::Kind::kUninitialized: case Value::Kind::kUninitialized:
out << "unknown register"; out << "unknown value";
break; break;
} }
return out; return out;

View File

@ -12,8 +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.
#ifndef SRC_TINT_IR_REGISTER_H_ #ifndef SRC_TINT_IR_VALUE_H_
#define SRC_TINT_IR_REGISTER_H_ #define SRC_TINT_IR_VALUE_H_
#include <ostream> #include <ostream>
#include <variant> #include <variant>
@ -23,37 +23,37 @@
namespace tint::ir { namespace tint::ir {
/// Register in the IR. The register can be one of several types these include, but aren't limited /// 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 register determines the type of data stored /// to, `f32`, `u32`, `temp`, `var`. The type of the value determines the type of data stored
/// in the register. /// in the value.
class Register { class Value {
public: public:
/// A register id. /// A value id.
using Id = uint32_t; using Id = uint32_t;
/// The type of the register /// The type of the value
enum class Kind { enum class Kind {
/// A uninitialized register /// A uninitialized value
kUninitialized, kUninitialized,
/// A temporary allocated register /// A temporary allocated value
kTemp, kTemp,
/// A f32 register /// A f32 value
kF32, kF32,
/// A f16 register /// A f16 value
kF16, kF16,
/// An i32 register /// An i32 value
kI32, kI32,
/// A u32 register /// A u32 value
kU32, kU32,
/// A variable register /// A variable value
kVar, kVar,
/// A boolean register /// A boolean value
kBool, kBool,
}; };
/// Stores data for a given variable. There will be multiple `VarData` entries for a given `id`. /// 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 /// 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` /// increasing). As the variable is stored too a new value will be created and the the `id`
/// will be incremented. /// will be incremented.
struct VarData { struct VarData {
/// The symbol for the variable /// The symbol for the variable
@ -64,106 +64,106 @@ class Register {
}; };
/// Constructor /// Constructor
/// Creates a uninitialized register /// Creates a uninitialized value
Register(); Value();
/// Constructor /// Constructor
/// @param id the id for the register /// @param id the id for the value
explicit Register(Id id); explicit Value(Id id);
/// Constructor /// Constructor
/// @param s the symbol for the register /// @param s the symbol for the value
/// @param id the id for the register /// @param id the id for the value
Register(Symbol s, Id id); Value(Symbol s, Id id);
/// Constructor /// Constructor
/// @param b the `bool` value to store in the register /// @param b the `bool` value to store in the value
explicit Register(bool b); explicit Value(bool b);
/// Constructor /// Constructor
/// @param f the `f32` value to store in the register /// @param f the `f32` value to store in the value
explicit Register(f32 f); explicit Value(f32 f);
/// Constructor /// Constructor
/// @param f the `f16` value to store in the register /// @param f the `f16` value to store in the value
explicit Register(f16 f); explicit Value(f16 f);
/// Constructor /// Constructor
/// @param u the `u32` value to store in the register /// @param u the `u32` value to store in the value
explicit Register(u32 u); explicit Value(u32 u);
/// Constructor /// Constructor
/// @param i the `i32` value to store in the register /// @param i the `i32` value to store in the value
explicit Register(i32 i); explicit Value(i32 i);
/// Destructor /// Destructor
~Register(); ~Value();
/// Copy constructor /// Copy constructor
/// @param o the register to copy from /// @param o the value to copy from
Register(const Register& o); Value(const Value& o);
/// Move constructor /// Move constructor
/// @param o the register to move from /// @param o the value to move from
Register(Register&& o); Value(Value&& o);
/// Copy assign /// Copy assign
/// @param o the register to copy from /// @param o the value to copy from
/// @returns this /// @returns this
Register& operator=(const Register& o); Value& operator=(const Value& o);
/// Move assign /// Move assign
/// @param o the register to move from /// @param o the value to move from
/// @returns this /// @returns this
Register& operator=(Register&& o); Value& operator=(Value&& o);
/// @returns true if this is a temporary register /// @returns true if this is a temporary value
bool IsTemp() const { return kind_ == Kind::kTemp; } bool IsTemp() const { return kind_ == Kind::kTemp; }
/// @returns true if this is a f32 register /// @returns true if this is a f32 value
bool IsF32() const { return kind_ == Kind::kF32; } bool IsF32() const { return kind_ == Kind::kF32; }
/// @returns true if this is a f16 register /// @returns true if this is a f16 value
bool IsF16() const { return kind_ == Kind::kF16; } bool IsF16() const { return kind_ == Kind::kF16; }
/// @returns true if this is an i32 register /// @returns true if this is an i32 value
bool IsI32() const { return kind_ == Kind::kI32; } bool IsI32() const { return kind_ == Kind::kI32; }
/// @returns true if this is a u32 register /// @returns true if this is a u32 value
bool IsU32() const { return kind_ == Kind::kU32; } bool IsU32() const { return kind_ == Kind::kU32; }
/// @returns true if this is a var register /// @returns true if this is a var value
bool IsVar() const { return kind_ == Kind::kVar; } bool IsVar() const { return kind_ == Kind::kVar; }
/// @returns true if this is a bool register /// @returns true if this is a bool value
bool IsBool() const { return kind_ == Kind::kBool; } bool IsBool() const { return kind_ == Kind::kBool; }
/// @returns the kind of register /// @returns the kind of value
Kind GetKind() const { return kind_; } Kind GetKind() const { return kind_; }
/// @returns the register data as a `f32`. /// @returns the value data as a `f32`.
/// @note, must only be called if `IsF32()` is true /// @note, must only be called if `IsF32()` is true
f32 AsF32() const { return std::get<f32>(data_); } f32 AsF32() const { return std::get<f32>(data_); }
/// @returns the register data as a `f16`. /// @returns the value data as a `f16`.
/// @note, must only be called if `IsF16()` is true /// @note, must only be called if `IsF16()` is true
f16 AsF16() const { return std::get<f16>(data_); } f16 AsF16() const { return std::get<f16>(data_); }
/// @returns the register data as an `i32`. /// @returns the value data as an `i32`.
/// @note, must only be called if `IsI32()` is true /// @note, must only be called if `IsI32()` is true
i32 AsI32() const { return std::get<i32>(data_); } i32 AsI32() const { return std::get<i32>(data_); }
/// @returns the register data as a `u32`. /// @returns the value data as a `u32`.
/// @note, must only be called if `IsU32()` is true /// @note, must only be called if `IsU32()` is true
u32 AsU32() const { return std::get<u32>(data_); } u32 AsU32() const { return std::get<u32>(data_); }
/// @returns the register data as an `Id`. /// @returns the value data as an `Id`.
/// @note, must only be called if `IsTemp()` is true /// @note, must only be called if `IsTemp()` is true
Id AsId() const { return std::get<Id>(data_); } Id AsId() const { return std::get<Id>(data_); }
/// @returns the register data as a `VarData` structure. /// @returns the value data as a `VarData` structure.
/// @note, must only be called if `IsVar()` is true /// @note, must only be called if `IsVar()` is true
VarData AsVarData() const { return std::get<VarData>(data_); } VarData AsVarData() const { return std::get<VarData>(data_); }
/// @returns the register data as a `bool`. /// @returns the value data as a `bool`.
/// @note, must only be called if `IsBool()` is true /// @note, must only be called if `IsBool()` is true
bool AsBool() const { return std::get<bool>(data_); } bool AsBool() const { return std::get<bool>(data_); }
private: private:
/// The type of data stored in this register /// The type of data stored in this value
Kind kind_; Kind kind_;
/// The data stored in the register /// The data stored in the value
std::variant<Id, f32, f16, u32, i32, VarData, bool> data_; std::variant<Id, f32, f16, u32, i32, VarData, bool> data_;
}; };
std::ostream& operator<<(std::ostream& out, const Register& r); std::ostream& operator<<(std::ostream& out, const Value& r);
} // namespace tint::ir } // namespace tint::ir
#endif // SRC_TINT_IR_REGISTER_H_ #endif // SRC_TINT_IR_VALUE_H_

183
src/tint/ir/value_test.cc Normal file
View File

@ -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