[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:
parent
3728a505d6
commit
62a07738c8
|
@ -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()
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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(); }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
@ -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_
|
|
@ -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
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
@ -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_
|
|
@ -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
|
Loading…
Reference in New Issue