Convert ir::Constant over to use a constant::Value

This CL updaets the ir::Constant to store a constant::Value instead of the specific numbers
themselves.

Bug: tint:1718
Change-Id: I66b0a9643893b6079399daf61ee39ac5811e1eaf
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/114362
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair 2022-12-15 19:17:22 +00:00 committed by Dawn LUCI CQ
parent dd1e4e39f2
commit 19ebcb2230
20 changed files with 602 additions and 500 deletions

View File

@ -1344,8 +1344,8 @@ int main(int argc, const char** argv) {
} else {
auto mod = result.Move();
if (options.dump_ir) {
tint::ir::Disassembler d;
std::cout << d.Disassemble(mod) << std::endl;
tint::ir::Disassembler d(mod);
std::cout << d.Disassemble() << std::endl;
}
if (options.dump_ir_graph) {
auto graph = tint::ir::Debug::AsDotGraph(&mod);

View File

@ -28,9 +28,9 @@ Binary::Binary(Kind kind, const Value* result, const Value* lhs, const Value* rh
Binary::~Binary() = default;
std::ostream& Binary::ToString(std::ostream& out) const {
Result()->ToString(out) << " = ";
lhs_->ToString(out) << " ";
std::ostream& Binary::ToString(std::ostream& out, const SymbolTable& st) const {
Result()->ToString(out, st) << " = ";
lhs_->ToString(out, st) << " ";
switch (GetKind()) {
case Binary::Kind::kAdd:
@ -89,7 +89,7 @@ std::ostream& Binary::ToString(std::ostream& out) const {
break;
}
out << " ";
rhs_->ToString(out);
rhs_->ToString(out, st);
return out;
}

View File

@ -20,6 +20,7 @@
#include "src/tint/castable.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/value.h"
#include "src/tint/symbol_table.h"
namespace tint::ir {
@ -79,8 +80,9 @@ class Binary : public Castable<Binary, Instruction> {
/// Write the instruction to the given stream
/// @param out the stream to write to
/// @param st the symbol table
/// @returns the stream
std::ostream& ToString(std::ostream& out) const override;
std::ostream& ToString(std::ostream& out, const SymbolTable& st) const override;
private:
Kind kind_;

View File

@ -20,13 +20,15 @@
namespace tint::ir {
namespace {
using namespace tint::number_suffixes; // NOLINT
//
using IR_InstructionTest = TestHelper;
TEST_F(IR_InstructionTest, CreateAnd) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.And(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.And(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kAnd);
@ -34,17 +36,17 @@ TEST_F(IR_InstructionTest, CreateAnd) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 & 2");
}
@ -52,7 +54,7 @@ TEST_F(IR_InstructionTest, CreateOr) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.Or(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.Or(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kOr);
@ -60,17 +62,17 @@ TEST_F(IR_InstructionTest, CreateOr) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 | 2");
}
@ -78,7 +80,7 @@ TEST_F(IR_InstructionTest, CreateXor) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.Xor(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.Xor(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kXor);
@ -86,17 +88,17 @@ TEST_F(IR_InstructionTest, CreateXor) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 ^ 2");
}
@ -104,8 +106,7 @@ TEST_F(IR_InstructionTest, CreateLogicalAnd) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr =
b.builder.LogicalAnd(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.LogicalAnd(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kLogicalAnd);
@ -113,17 +114,17 @@ TEST_F(IR_InstructionTest, CreateLogicalAnd) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 && 2");
}
@ -131,7 +132,7 @@ TEST_F(IR_InstructionTest, CreateLogicalOr) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.LogicalOr(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.LogicalOr(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kLogicalOr);
@ -139,17 +140,17 @@ TEST_F(IR_InstructionTest, CreateLogicalOr) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 || 2");
}
@ -157,7 +158,7 @@ TEST_F(IR_InstructionTest, CreateEqual) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.Equal(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.Equal(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kEqual);
@ -165,17 +166,17 @@ TEST_F(IR_InstructionTest, CreateEqual) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 == 2");
}
@ -183,7 +184,7 @@ TEST_F(IR_InstructionTest, CreateNotEqual) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.NotEqual(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.NotEqual(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kNotEqual);
@ -191,17 +192,17 @@ TEST_F(IR_InstructionTest, CreateNotEqual) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 != 2");
}
@ -209,7 +210,7 @@ TEST_F(IR_InstructionTest, CreateLessThan) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.LessThan(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.LessThan(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kLessThan);
@ -217,17 +218,17 @@ TEST_F(IR_InstructionTest, CreateLessThan) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 < 2");
}
@ -235,8 +236,7 @@ TEST_F(IR_InstructionTest, CreateGreaterThan) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr =
b.builder.GreaterThan(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.GreaterThan(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kGreaterThan);
@ -244,17 +244,17 @@ TEST_F(IR_InstructionTest, CreateGreaterThan) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 > 2");
}
@ -262,8 +262,7 @@ TEST_F(IR_InstructionTest, CreateLessThanEqual) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr =
b.builder.LessThanEqual(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.LessThanEqual(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kLessThanEqual);
@ -271,17 +270,17 @@ TEST_F(IR_InstructionTest, CreateLessThanEqual) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 <= 2");
}
@ -290,7 +289,7 @@ TEST_F(IR_InstructionTest, CreateGreaterThanEqual) {
b.builder.next_temp_id = Temp::Id(42);
const auto* instr =
b.builder.GreaterThanEqual(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
b.builder.GreaterThanEqual(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kGreaterThanEqual);
@ -298,17 +297,17 @@ TEST_F(IR_InstructionTest, CreateGreaterThanEqual) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 >= 2");
}
@ -316,7 +315,7 @@ TEST_F(IR_InstructionTest, CreateShiftLeft) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.ShiftLeft(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.ShiftLeft(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kShiftLeft);
@ -324,17 +323,17 @@ TEST_F(IR_InstructionTest, CreateShiftLeft) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 << 2");
}
@ -342,8 +341,7 @@ TEST_F(IR_InstructionTest, CreateShiftRight) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr =
b.builder.ShiftRight(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.ShiftRight(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kShiftRight);
@ -351,17 +349,17 @@ TEST_F(IR_InstructionTest, CreateShiftRight) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 >> 2");
}
@ -369,7 +367,7 @@ TEST_F(IR_InstructionTest, CreateAdd) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.Add(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.Add(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kAdd);
@ -377,17 +375,17 @@ TEST_F(IR_InstructionTest, CreateAdd) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 + 2");
}
@ -395,7 +393,7 @@ TEST_F(IR_InstructionTest, CreateSubtract) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.Subtract(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.Subtract(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kSubtract);
@ -403,17 +401,17 @@ TEST_F(IR_InstructionTest, CreateSubtract) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 - 2");
}
@ -421,7 +419,7 @@ TEST_F(IR_InstructionTest, CreateMultiply) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.Multiply(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.Multiply(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kMultiply);
@ -429,17 +427,17 @@ TEST_F(IR_InstructionTest, CreateMultiply) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 * 2");
}
@ -447,7 +445,7 @@ TEST_F(IR_InstructionTest, CreateDivide) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.Divide(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.Divide(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kDivide);
@ -455,17 +453,17 @@ TEST_F(IR_InstructionTest, CreateDivide) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 / 2");
}
@ -473,7 +471,7 @@ TEST_F(IR_InstructionTest, CreateModulo) {
auto& b = CreateEmptyBuilder();
b.builder.next_temp_id = Temp::Id(42);
const auto* instr = b.builder.Modulo(b.builder.Constant(i32(4)), b.builder.Constant(i32(2)));
const auto* instr = b.builder.Modulo(b.builder.Constant(4_i), b.builder.Constant(2_i));
EXPECT_EQ(instr->GetKind(), Binary::Kind::kModulo);
@ -481,17 +479,17 @@ TEST_F(IR_InstructionTest, CreateModulo) {
EXPECT_EQ(Temp::Id(42), instr->Result()->As<Temp>()->AsId());
ASSERT_TRUE(instr->LHS()->Is<Constant>());
auto lhs = instr->LHS()->As<Constant>();
ASSERT_TRUE(lhs->IsI32());
EXPECT_EQ(i32(4), lhs->AsI32());
auto lhs = instr->LHS()->As<Constant>()->value;
ASSERT_TRUE(lhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(4_i, lhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
ASSERT_TRUE(instr->RHS()->Is<Constant>());
auto rhs = instr->RHS()->As<Constant>();
ASSERT_TRUE(rhs->IsI32());
EXPECT_EQ(i32(2), rhs->AsI32());
auto rhs = instr->RHS()->As<Constant>()->value;
ASSERT_TRUE(rhs->Is<constant::Scalar<i32>>());
EXPECT_EQ(2_i, rhs->As<constant::Scalar<i32>>()->ValueAs<i32>());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 % 2");
}

View File

@ -15,6 +15,9 @@
#ifndef SRC_TINT_IR_BUILDER_H_
#define SRC_TINT_IR_BUILDER_H_
#include <utility>
#include "src/tint/constant/scalar.h"
#include "src/tint/ir/binary.h"
#include "src/tint/ir/constant.h"
#include "src/tint/ir/function.h"
@ -25,6 +28,11 @@
#include "src/tint/ir/temp.h"
#include "src/tint/ir/terminator.h"
#include "src/tint/ir/value.h"
#include "src/tint/type/bool.h"
#include "src/tint/type/f16.h"
#include "src/tint/type/f32.h"
#include "src/tint/type/i32.h"
#include "src/tint/type/u32.h"
// Forward Declarations
namespace tint {
@ -85,14 +93,56 @@ class Builder {
/// @param to the node to branch too
void Branch(Block* from, FlowNode* to);
/// Creates a new Constant
/// Creates a constant::Value
/// @param args the arguments
/// @returns the new constant value
template <typename T, typename... ARGS>
traits::EnableIf<traits::IsTypeOrDerived<T, constant::Value>, const T>* create(ARGS&&... args) {
return ir.constants.Create<T>(std::forward<ARGS>(args)...);
}
/// Creates a new ir::Constant
/// @param val the constant value
/// @returns the new constant
template <typename T>
const ir::Constant* Constant(T val) {
const ir::Constant* Constant(const constant::Value* val) {
return ir.values.Create<ir::Constant>(val);
}
/// Creates a ir::Constant for an i32 Scalar
/// @param v the value
/// @returns the new constant
const ir::Constant* Constant(i32 v) {
return Constant(create<constant::Scalar<i32>>(ir.types.Get<type::I32>(), v));
}
/// Creates a ir::Constant for a u32 Scalar
/// @param v the value
/// @returns the new constant
const ir::Constant* Constant(u32 v) {
return Constant(create<constant::Scalar<u32>>(ir.types.Get<type::U32>(), v));
}
/// Creates a ir::Constant for a f32 Scalar
/// @param v the value
/// @returns the new constant
const ir::Constant* Constant(f32 v) {
return Constant(create<constant::Scalar<f32>>(ir.types.Get<type::F32>(), v));
}
/// Creates a ir::Constant for a f16 Scalar
/// @param v the value
/// @returns the new constant
const ir::Constant* Constant(f16 v) {
return Constant(create<constant::Scalar<f16>>(ir.types.Get<type::F16>(), v));
}
/// Creates a ir::Constant for a bool Scalar
/// @param v the value
/// @returns the new constant
const ir::Constant* Constant(bool v) {
return Constant(create<constant::Scalar<bool>>(ir.types.Get<type::Bool>(), v));
}
/// Creates a new Temporary
/// @returns the new temporary
const ir::Temp* Temp() { return ir.values.Create<ir::Temp>(AllocateTempId()); }

View File

@ -41,6 +41,7 @@
#include "src/tint/ir/switch.h"
#include "src/tint/ir/terminator.h"
#include "src/tint/program.h"
#include "src/tint/sem/expression.h"
#include "src/tint/sem/module.h"
namespace tint::ir {
@ -628,30 +629,24 @@ utils::Result<const Value*> BuilderImpl::EmitBinary(const ast::BinaryExpression*
}
utils::Result<const Value*> BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) {
return tint::Switch( //
lit,
[&](const ast::BoolLiteralExpression* l) {
return utils::Result<const Value*>(builder.Constant(l->value));
},
[&](const ast::FloatLiteralExpression* l) {
if (l->suffix == ast::FloatLiteralExpression::Suffix::kF) {
return utils::Result<const Value*>(
builder.Constant(f32(static_cast<float>(l->value))));
}
return utils::Result<const Value*>(builder.Constant(f16(static_cast<float>(l->value))));
},
[&](const ast::IntLiteralExpression* l) {
if (l->suffix == ast::IntLiteralExpression::Suffix::kI) {
return utils::Result<const Value*>(builder.Constant(i32(l->value)));
}
return utils::Result<const Value*>(builder.Constant(u32(l->value)));
},
[&](Default) {
diagnostics_.add_warning(tint::diag::System::IR,
"unknown literal type: " + std::string(lit->TypeInfo().name),
lit->source);
return utils::Failure;
});
auto* sem = builder.ir.program->Sem().Get(lit);
if (!sem) {
diagnostics_.add_error(
tint::diag::System::IR,
"Failed to get semantic information for node " + std::string(lit->TypeInfo().name),
lit->source);
return utils::Failure;
}
auto* cv = sem->ConstantValue();
if (!cv) {
diagnostics_.add_error(
tint::diag::System::IR,
"Failed to get constant value for node " + std::string(lit->TypeInfo().name),
lit->source);
return utils::Failure;
}
return utils::Result<const Value*>(builder.Constant(cv));
}
bool BuilderImpl::EmitType(const ast::Type* ty) {

View File

@ -102,9 +102,9 @@ TEST_F(IR_BuilderImplTest, IfStatement) {
// Check condition
ASSERT_TRUE(flow->condition->Is<Constant>());
auto* instr = flow->condition->As<Constant>();
ASSERT_TRUE(instr->IsBool());
EXPECT_TRUE(instr->AsBool());
auto* instr = flow->condition->As<Constant>()->value;
ASSERT_TRUE(instr->Is<constant::Scalar<bool>>());
EXPECT_TRUE(instr->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
TEST_F(IR_BuilderImplTest, IfStatement_TrueReturns) {
@ -504,9 +504,9 @@ TEST_F(IR_BuilderImplTest, Loop_WithReturn) {
// Check condition
ASSERT_TRUE(if_flow->condition->Is<Constant>());
auto* instr = if_flow->condition->As<Constant>();
ASSERT_TRUE(instr->IsBool());
EXPECT_TRUE(instr->AsBool());
auto* instr = if_flow->condition->As<Constant>()->value;
ASSERT_TRUE(instr->Is<constant::Scalar<bool>>());
EXPECT_TRUE(instr->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn) {
@ -950,9 +950,9 @@ TEST_F(IR_BuilderImplTest, While) {
// Check condition
ASSERT_TRUE(if_flow->condition->Is<Constant>());
auto* instr = if_flow->condition->As<Constant>();
ASSERT_TRUE(instr->IsBool());
EXPECT_FALSE(instr->AsBool());
auto* instr = if_flow->condition->As<Constant>()->value;
ASSERT_TRUE(instr->Is<constant::Scalar<bool>>());
EXPECT_FALSE(instr->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
TEST_F(IR_BuilderImplTest, While_Return) {
@ -1075,9 +1075,9 @@ TEST_F(IR_BuilderImplTest, DISABLED_For) {
// Check condition
ASSERT_TRUE(if_flow->condition->Is<Constant>());
auto* instr = if_flow->condition->As<Constant>();
ASSERT_TRUE(instr->IsBool());
EXPECT_FALSE(instr->AsBool());
auto* instr = if_flow->condition->As<Constant>()->value;
ASSERT_TRUE(instr->Is<constant::Scalar<bool>>());
EXPECT_FALSE(instr->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) {
@ -1176,9 +1176,9 @@ TEST_F(IR_BuilderImplTest, Switch) {
// Check condition
ASSERT_TRUE(flow->condition->Is<Constant>());
auto* instr = flow->condition->As<Constant>();
ASSERT_TRUE(instr->IsI32());
EXPECT_EQ(1_i, instr->AsI32());
auto* instr = flow->condition->As<Constant>()->value;
ASSERT_TRUE(instr->Is<constant::Scalar<i32>>());
EXPECT_EQ(1_i, instr->As<constant::Scalar<i32>>()->ValueAs<i32>());
}
TEST_F(IR_BuilderImplTest, Switch_OnlyDefault) {
@ -1342,283 +1342,378 @@ TEST_F(IR_BuilderImplTest, Switch_AllReturn) {
}
TEST_F(IR_BuilderImplTest, EmitLiteral_Bool_True) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitLiteral(Expr(true));
ASSERT_TRUE(r);
auto* expr = Expr(true);
GlobalVar("a", ty.bool_(), ast::AddressSpace::kPrivate, expr);
auto& b = CreateBuilder();
auto r = b.EmitLiteral(expr);
ASSERT_TRUE(r) << b.error();
ASSERT_TRUE(r.Get()->Is<Constant>());
auto* val = r.Get()->As<Constant>();
EXPECT_TRUE(val->IsBool());
EXPECT_TRUE(val->AsBool());
auto* val = r.Get()->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
EXPECT_TRUE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
TEST_F(IR_BuilderImplTest, EmitLiteral_Bool_False) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitLiteral(Expr(false));
ASSERT_TRUE(r);
auto* expr = Expr(false);
GlobalVar("a", ty.bool_(), ast::AddressSpace::kPrivate, expr);
auto& b = CreateBuilder();
auto r = b.EmitLiteral(expr);
ASSERT_TRUE(r) << b.error();
ASSERT_TRUE(r.Get()->Is<Constant>());
auto* val = r.Get()->As<Constant>();
EXPECT_TRUE(val->IsBool());
EXPECT_FALSE(val->AsBool());
auto* val = r.Get()->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<bool>>());
EXPECT_FALSE(val->As<constant::Scalar<bool>>()->ValueAs<bool>());
}
TEST_F(IR_BuilderImplTest, EmitLiteral_F32) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitLiteral(Expr(1.2_f));
ASSERT_TRUE(r);
auto* expr = Expr(1.2_f);
GlobalVar("a", ty.f32(), ast::AddressSpace::kPrivate, expr);
auto& b = CreateBuilder();
auto r = b.EmitLiteral(expr);
ASSERT_TRUE(r) << b.error();
ASSERT_TRUE(r.Get()->Is<Constant>());
auto* val = r.Get()->As<Constant>();
EXPECT_TRUE(val->IsF32());
EXPECT_EQ(1.2_f, val->AsF32());
auto* val = r.Get()->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<f32>>());
EXPECT_EQ(1.2_f, val->As<constant::Scalar<f32>>()->ValueAs<f32>());
}
TEST_F(IR_BuilderImplTest, EmitLiteral_F16) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitLiteral(Expr(1.2_h));
ASSERT_TRUE(r);
Enable(ast::Extension::kF16);
auto* expr = Expr(1.2_h);
GlobalVar("a", ty.f16(), ast::AddressSpace::kPrivate, expr);
auto& b = CreateBuilder();
auto r = b.EmitLiteral(expr);
ASSERT_TRUE(r) << b.error();
ASSERT_TRUE(r.Get()->Is<Constant>());
auto* val = r.Get()->As<Constant>();
EXPECT_TRUE(val->IsF16());
EXPECT_EQ(1.2_h, val->AsF16());
auto* val = r.Get()->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<f16>>());
EXPECT_EQ(1.2_h, val->As<constant::Scalar<f16>>()->ValueAs<f32>());
}
TEST_F(IR_BuilderImplTest, EmitLiteral_I32) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitLiteral(Expr(-2_i));
ASSERT_TRUE(r);
auto* expr = Expr(-2_i);
GlobalVar("a", ty.i32(), ast::AddressSpace::kPrivate, expr);
auto& b = CreateBuilder();
auto r = b.EmitLiteral(expr);
ASSERT_TRUE(r) << b.error();
ASSERT_TRUE(r.Get()->Is<Constant>());
auto* val = r.Get()->As<Constant>();
EXPECT_TRUE(val->IsI32());
EXPECT_EQ(-2_i, val->AsI32());
auto* val = r.Get()->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<i32>>());
EXPECT_EQ(-2_i, val->As<constant::Scalar<i32>>()->ValueAs<f32>());
}
TEST_F(IR_BuilderImplTest, EmitLiteral_U32) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitLiteral(Expr(2_u));
ASSERT_TRUE(r);
auto* expr = Expr(2_u);
GlobalVar("a", ty.u32(), ast::AddressSpace::kPrivate, expr);
auto& b = CreateBuilder();
auto r = b.EmitLiteral(expr);
ASSERT_TRUE(r) << b.error();
ASSERT_TRUE(r.Get()->Is<Constant>());
auto* val = r.Get()->As<Constant>();
EXPECT_TRUE(val->IsU32());
EXPECT_EQ(2_u, val->AsU32());
auto* val = r.Get()->As<Constant>()->value;
EXPECT_TRUE(val->Is<constant::Scalar<u32>>());
EXPECT_EQ(2_u, val->As<constant::Scalar<u32>>()->ValueAs<f32>());
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Add(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Add(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 + 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Sub(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Sub(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 - 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Mul(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Mul(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 * 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Div(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Div(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 / 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Mod(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Mod(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 % 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(And(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = And(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 & 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Or(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Or(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 | 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Xor(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Xor(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 ^ 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(LogicalAnd(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = LogicalAnd(true, false);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 && 4
EXPECT_EQ(d.AsString(), R"(%1 = true && false
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(LogicalOr(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = LogicalOr(false, true);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 || 4
EXPECT_EQ(d.AsString(), R"(%1 = false || true
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Eqaul) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Equal(3_u, 4_u));
ASSERT_TRUE(r);
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Equal) {
auto* expr = Equal(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 == 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(NotEqual(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = NotEqual(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 != 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(LessThan(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = LessThan(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 < 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(GreaterThan(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = GreaterThan(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 > 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(LessThanEqual(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = LessThanEqual(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 <= 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(GreaterThanEqual(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = GreaterThanEqual(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >= 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Shl(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Shl(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 << 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(Shr(3_u, 4_u));
ASSERT_TRUE(r);
auto* expr = Shr(3_u, 4_u);
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >> 4
)");
}
TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) {
auto& b = CreateEmptyBuilder();
auto r = b.EmitExpression(LogicalOr( //
LessThan(1_u, Add(Shr(3_u, 4_u), 9_u)), GreaterThan(2.5_f, Div(6.7_f, Mul(2.3_f, 5.5_f)))));
ASSERT_TRUE(r);
auto* expr = LogicalOr(LessThan(1_u, Add(Shr(3_u, 4_u), 9_u)),
GreaterThan(2.5_f, Div(6.7_f, Mul(2.3_f, 5.5_f))));
WrapInFunction(expr);
Disassembler d;
auto& b = CreateBuilder();
InjectFlowBlock();
auto r = b.EmitExpression(expr);
ASSERT_TRUE(r) << b.error();
Disassembler d(b.builder.ir);
d.EmitBlockInstructions(b.current_flow_block);
EXPECT_EQ(d.AsString(), R"(%1 = 3 >> 4
%2 = %1 + 9
%3 = 1 < %2
%4 = 2.300000 * 5.500000
%5 = 6.700000 / %4
%6 = 2.500000 > %5
%4 = 2.3 * 5.5
%5 = 6.7 / %4
%6 = 2.5 > %5
%7 = %3 || %6
)");
}

View File

@ -16,40 +16,48 @@
#include <string>
#include "src/tint/constant/composite.h"
#include "src/tint/constant/scalar.h"
#include "src/tint/constant/splat.h"
TINT_INSTANTIATE_TYPEINFO(tint::ir::Constant);
namespace tint::ir {
Constant::Constant(f32 f) : kind_(Kind::kF32), data_(f) {}
Constant::Constant(f16 f) : kind_(Kind::kF16), data_(f) {}
Constant::Constant(u32 u) : kind_(Kind::kU32), data_(u) {}
Constant::Constant(i32 i) : kind_(Kind::kI32), data_(i) {}
Constant::Constant(bool b) : kind_(Kind::kBool), data_(b) {}
Constant::Constant(const constant::Value* val) : value(val) {}
Constant::~Constant() = default;
std::ostream& Constant::ToString(std::ostream& out) const {
switch (GetKind()) {
case Constant::Kind::kF32:
out << std::to_string(AsF32().value);
break;
case Constant::Kind::kF16:
out << std::to_string(AsF16().value);
break;
case Constant::Kind::kI32:
out << std::to_string(AsI32().value);
break;
case Constant::Kind::kU32:
out << std::to_string(AsU32().value);
break;
case Constant::Kind::kBool:
out << (AsBool() ? "true" : "false");
break;
}
std::ostream& Constant::ToString(std::ostream& out, const SymbolTable& st) const {
std::function<void(const constant::Value*)> emit = [&](const constant::Value* c) {
Switch(
c,
[&](const constant::Scalar<AFloat>* scalar) { out << scalar->ValueAs<AFloat>().value; },
[&](const constant::Scalar<AInt>* scalar) { out << scalar->ValueAs<AInt>().value; },
[&](const constant::Scalar<i32>* scalar) { out << scalar->ValueAs<i32>().value; },
[&](const constant::Scalar<u32>* scalar) { out << scalar->ValueAs<u32>().value; },
[&](const constant::Scalar<f32>* scalar) { out << scalar->ValueAs<f32>().value; },
[&](const constant::Scalar<f16>* scalar) { out << scalar->ValueAs<f16>().value; },
[&](const constant::Scalar<bool>* scalar) {
out << (scalar->ValueAs<bool>() ? "true" : "false");
},
[&](const constant::Splat* splat) {
out << splat->Type()->FriendlyName(st) << "(";
emit(splat->Index(0));
out << ")";
},
[&](const constant::Composite* composite) {
out << composite->Type()->FriendlyName(st) << "(";
for (const auto* elem : composite->elements) {
if (elem != composite->elements[0]) {
out << ", ";
}
emit(elem);
}
out << ")";
});
};
emit(value);
return out;
}

View File

@ -16,100 +16,29 @@
#define SRC_TINT_IR_CONSTANT_H_
#include <ostream>
#include <variant>
#include "src/tint/constant/value.h"
#include "src/tint/ir/value.h"
#include "src/tint/number.h"
#include "src/tint/symbol_table.h"
namespace tint::ir {
/// Constant in the IR. The constant can be one of several types these include, but aren't limited
/// to, `f32`, `u32`, `bool`. The type of the constant determines the type of data stored.
/// Constant in the IR.
class Constant : public Castable<Constant, Value> {
public:
/// The type of the constant
enum class Kind {
/// A f32 constant
kF32,
/// A f16 constant
kF16,
/// An i32 constant
kI32,
/// A u32 constant
kU32,
/// A boolean constant
kBool,
};
/// Constructor
/// @param b the `bool` constant to store in the constant
explicit Constant(bool b);
/// Constructor
/// @param f the `f32` constant to store in the constant
explicit Constant(f32 f);
/// Constructor
/// @param f the `f16` constant to store in the constant
explicit Constant(f16 f);
/// Constructor
/// @param u the `u32` constant to store in the constant
explicit Constant(u32 u);
/// Constructor
/// @param i the `i32` constant to store in the constant
explicit Constant(i32 i);
/// Destructor
/// @param val the value stored in the constant
explicit Constant(const constant::Value* val);
~Constant() override;
Constant(const Constant&) = delete;
Constant(Constant&&) = delete;
Constant& operator=(const Constant&) = delete;
Constant& operator=(Constant&&) = delete;
/// @returns true if this is a f32 constant
bool IsF32() const { return kind_ == Kind::kF32; }
/// @returns true if this is a f16 constant
bool IsF16() const { return kind_ == Kind::kF16; }
/// @returns true if this is an i32 constant
bool IsI32() const { return kind_ == Kind::kI32; }
/// @returns true if this is a u32 constant
bool IsU32() const { return kind_ == Kind::kU32; }
/// @returns true if this is a bool constant
bool IsBool() const { return kind_ == Kind::kBool; }
/// @returns the kind of constant
Kind GetKind() const { return kind_; }
/// @returns the constant data as a `f32`.
/// @note, must only be called if `IsF32()` is true
f32 AsF32() const { return std::get<f32>(data_); }
/// @returns the constant data as a `f16`.
/// @note, must only be called if `IsF16()` is true
f16 AsF16() const { return std::get<f16>(data_); }
/// @returns the constant data as an `i32`.
/// @note, must only be called if `IsI32()` is true
i32 AsI32() const { return std::get<i32>(data_); }
/// @returns the constant data as a `u32`.
/// @note, must only be called if `IsU32()` is true
u32 AsU32() const { return std::get<u32>(data_); }
/// @returns the constant data as a `bool`.
/// @note, must only be called if `IsBool()` is true
bool AsBool() const { return std::get<bool>(data_); }
/// Write the constant to the given stream
/// @param out the stream to write to
/// @param st the symbol table
/// @returns the stream
std::ostream& ToString(std::ostream& out) const override;
std::ostream& ToString(std::ostream& out, const SymbolTable& st) const override;
private:
/// The type of data stored in this constant
Kind kind_;
/// The data stored in the constant
std::variant<f32, f16, u32, i32, bool> data_;
/// The constants value
const constant::Value* const value;
};
} // namespace tint::ir

View File

@ -29,17 +29,17 @@ TEST_F(IR_ConstantTest, f32) {
std::stringstream str;
auto* val = b.builder.Constant(1.2_f);
EXPECT_EQ(1.2_f, val->AsF32());
auto* c = b.builder.Constant(1.2_f);
EXPECT_EQ(1.2_f, c->value->As<constant::Scalar<f32>>()->ValueAs<f32>());
val->ToString(str);
EXPECT_EQ("1.200000", str.str());
c->ToString(str, program->Symbols());
EXPECT_EQ("1.2", str.str());
EXPECT_TRUE(val->IsF32());
EXPECT_FALSE(val->IsF16());
EXPECT_FALSE(val->IsI32());
EXPECT_FALSE(val->IsU32());
EXPECT_FALSE(val->IsBool());
EXPECT_TRUE(c->value->Is<constant::Scalar<f32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<i32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<u32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<bool>>());
}
TEST_F(IR_ConstantTest, f16) {
@ -47,17 +47,17 @@ TEST_F(IR_ConstantTest, f16) {
std::stringstream str;
auto* val = b.builder.Constant(1.1_h);
EXPECT_EQ(1.1_h, val->AsF16());
auto* c = b.builder.Constant(1.1_h);
EXPECT_EQ(1.1_h, c->value->As<constant::Scalar<f16>>()->ValueAs<f16>());
val->ToString(str);
EXPECT_EQ("1.099609", str.str());
c->ToString(str, program->Symbols());
EXPECT_EQ("1.09961", str.str());
EXPECT_FALSE(val->IsF32());
EXPECT_TRUE(val->IsF16());
EXPECT_FALSE(val->IsI32());
EXPECT_FALSE(val->IsU32());
EXPECT_FALSE(val->IsBool());
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
EXPECT_TRUE(c->value->Is<constant::Scalar<f16>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<i32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<u32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<bool>>());
}
TEST_F(IR_ConstantTest, i32) {
@ -65,17 +65,17 @@ TEST_F(IR_ConstantTest, i32) {
std::stringstream str;
auto* val = b.builder.Constant(1_i);
EXPECT_EQ(1_i, val->AsI32());
auto* c = b.builder.Constant(1_i);
EXPECT_EQ(1_i, c->value->As<constant::Scalar<i32>>()->ValueAs<i32>());
val->ToString(str);
c->ToString(str, program->Symbols());
EXPECT_EQ("1", str.str());
EXPECT_FALSE(val->IsF32());
EXPECT_FALSE(val->IsF16());
EXPECT_TRUE(val->IsI32());
EXPECT_FALSE(val->IsU32());
EXPECT_FALSE(val->IsBool());
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());
EXPECT_TRUE(c->value->Is<constant::Scalar<i32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<u32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<bool>>());
}
TEST_F(IR_ConstantTest, u32) {
@ -83,17 +83,17 @@ TEST_F(IR_ConstantTest, u32) {
std::stringstream str;
auto* val = b.builder.Constant(2_u);
EXPECT_EQ(2_u, val->AsU32());
auto* c = b.builder.Constant(2_u);
EXPECT_EQ(2_u, c->value->As<constant::Scalar<u32>>()->ValueAs<u32>());
val->ToString(str);
c->ToString(str, program->Symbols());
EXPECT_EQ("2", str.str());
EXPECT_FALSE(val->IsF32());
EXPECT_FALSE(val->IsF16());
EXPECT_FALSE(val->IsI32());
EXPECT_TRUE(val->IsU32());
EXPECT_FALSE(val->IsBool());
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<i32>>());
EXPECT_TRUE(c->value->Is<constant::Scalar<u32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<bool>>());
}
TEST_F(IR_ConstantTest, bool) {
@ -101,24 +101,24 @@ TEST_F(IR_ConstantTest, bool) {
std::stringstream str;
auto* val = b.builder.Constant(false);
EXPECT_FALSE(val->AsBool());
auto* c = b.builder.Constant(false);
EXPECT_FALSE(c->value->As<constant::Scalar<bool>>()->ValueAs<bool>());
val->ToString(str);
c->ToString(str, program->Symbols());
EXPECT_EQ("false", str.str());
str.str("");
val = b.builder.Constant(true);
EXPECT_TRUE(val->AsBool());
c = b.builder.Constant(true);
EXPECT_TRUE(c->value->As<constant::Scalar<bool>>()->ValueAs<bool>());
val->ToString(str);
c->ToString(str, program->Symbols());
EXPECT_EQ("true", str.str());
EXPECT_FALSE(val->IsF32());
EXPECT_FALSE(val->IsF16());
EXPECT_FALSE(val->IsI32());
EXPECT_FALSE(val->IsU32());
EXPECT_TRUE(val->IsBool());
EXPECT_FALSE(c->value->Is<constant::Scalar<f32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<i32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<u32>>());
EXPECT_TRUE(c->value->Is<constant::Scalar<bool>>());
}
} // namespace

View File

@ -50,7 +50,7 @@ class ScopedIndent {
} // namespace
Disassembler::Disassembler() = default;
Disassembler::Disassembler(const Module& mod) : mod_(mod) {}
Disassembler::~Disassembler() = default;
@ -63,7 +63,7 @@ std::ostream& Disassembler::Indent() {
void Disassembler::EmitBlockInstructions(const Block* b) {
for (const auto* instr : b->instructions) {
instr->ToString(out_) << std::endl;
instr->ToString(out_, mod_.program->Symbols()) << std::endl;
}
}
@ -144,8 +144,8 @@ void Disassembler::Walk(const FlowNode* node) {
[&](const ir::Terminator*) { Indent() << "Function end" << std::endl; });
}
std::string Disassembler::Disassemble(const Module& mod) {
for (const auto* func : mod.functions) {
std::string Disassembler::Disassemble() {
for (const auto* func : mod_.functions) {
Walk(func);
}
return out_.str();

View File

@ -28,13 +28,13 @@ namespace tint::ir {
class Disassembler {
public:
/// Constructor
Disassembler();
/// @param mod the module
explicit Disassembler(const Module& mod);
~Disassembler();
/// Returns the module as a string
/// @param mod the module to emit
/// @returns the string representation of the module
std::string Disassemble(const Module& mod);
std::string Disassemble();
/// Writes the block instructions to the stream
/// @param b the block containing the instructions
@ -47,6 +47,7 @@ class Disassembler {
std::ostream& Indent();
void Walk(const FlowNode* node);
const Module& mod_;
std::stringstream out_;
std::unordered_set<const FlowNode*> visited_;
std::unordered_set<const FlowNode*> stop_nodes_;

View File

@ -18,6 +18,7 @@
#include <ostream>
#include "src/tint/castable.h"
#include "src/tint/symbol_table.h"
namespace tint::ir {
@ -34,8 +35,9 @@ class Instruction : public Castable<Instruction> {
/// Write the instruction to the given stream
/// @param out the stream to write to
/// @param st the symbol table
/// @returns the stream
virtual std::ostream& ToString(std::ostream& out) const = 0;
virtual std::ostream& ToString(std::ostream& out, const SymbolTable& st) const = 0;
protected:
/// Constructor

View File

@ -44,7 +44,7 @@ TEST_F(IR_BinaryTest, CreateAnd) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 & 2");
}
@ -70,7 +70,7 @@ TEST_F(IR_BinaryTest, CreateOr) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 | 2");
}
@ -96,7 +96,7 @@ TEST_F(IR_BinaryTest, CreateXor) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 ^ 2");
}
@ -123,7 +123,7 @@ TEST_F(IR_BinaryTest, CreateLogicalAnd) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 && 2");
}
@ -149,7 +149,7 @@ TEST_F(IR_BinaryTest, CreateLogicalOr) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 || 2");
}
@ -175,7 +175,7 @@ TEST_F(IR_BinaryTest, CreateEqual) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 == 2");
}
@ -201,7 +201,7 @@ TEST_F(IR_BinaryTest, CreateNotEqual) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 != 2");
}
@ -227,7 +227,7 @@ TEST_F(IR_BinaryTest, CreateLessThan) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 < 2");
}
@ -254,7 +254,7 @@ TEST_F(IR_BinaryTest, CreateGreaterThan) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 > 2");
}
@ -281,7 +281,7 @@ TEST_F(IR_BinaryTest, CreateLessThanEqual) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 <= 2");
}
@ -308,7 +308,7 @@ TEST_F(IR_BinaryTest, CreateGreaterThanEqual) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 >= 2");
}
@ -334,7 +334,7 @@ TEST_F(IR_BinaryTest, CreateShiftLeft) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 << 2");
}
@ -361,7 +361,7 @@ TEST_F(IR_BinaryTest, CreateShiftRight) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 >> 2");
}
@ -387,7 +387,7 @@ TEST_F(IR_BinaryTest, CreateAdd) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 + 2");
}
@ -413,7 +413,7 @@ TEST_F(IR_BinaryTest, CreateSubtract) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 - 2");
}
@ -439,7 +439,7 @@ TEST_F(IR_BinaryTest, CreateMultiply) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 * 2");
}
@ -465,7 +465,7 @@ TEST_F(IR_BinaryTest, CreateDivide) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 / 2");
}
@ -491,7 +491,7 @@ TEST_F(IR_BinaryTest, CreateModulo) {
EXPECT_EQ(i32(2), rhs->AsI32());
std::stringstream str;
instr->ToString(str);
instr->ToString(str, program->Symbols());
EXPECT_EQ(str.str(), "%42 = 4 % 2");
}

View File

@ -17,9 +17,11 @@
#include <string>
#include "src/tint/constant/value.h"
#include "src/tint/ir/function.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/value.h"
#include "src/tint/type/manager.h"
#include "src/tint/utils/block_allocator.h"
#include "src/tint/utils/result.h"
#include "src/tint/utils/vector.h"
@ -68,6 +70,8 @@ class Module {
/// The flow node allocator
utils::BlockAllocator<FlowNode> flow_nodes;
/// The constant allocator
utils::BlockAllocator<constant::Value> constants;
/// The value allocator
utils::BlockAllocator<Value> values;
/// The instruction allocator
@ -80,6 +84,9 @@ class Module {
/// The source ast::Program this module was constucted from
const Program* program;
/// The type manager for the module
type::Manager types;
};
} // namespace tint::ir

View File

@ -24,7 +24,7 @@ Temp::Temp(Id id) : id_(id) {}
Temp::~Temp() = default;
std::ostream& Temp::ToString(std::ostream& out) const {
std::ostream& Temp::ToString(std::ostream& out, const SymbolTable&) const {
out << "%" << std::to_string(AsId());
return out;
}

View File

@ -18,6 +18,7 @@
#include <ostream>
#include "src/tint/ir/value.h"
#include "src/tint/symbol_table.h"
namespace tint::ir {
@ -45,8 +46,9 @@ class Temp : public Castable<Temp, Value> {
/// Write the temp to the given stream
/// @param out the stream to write to
/// @param st the symbol table
/// @returns the stream
std::ostream& ToString(std::ostream& out) const override;
std::ostream& ToString(std::ostream& out, const SymbolTable& st) const override;
private:
Id id_ = 0;

View File

@ -33,7 +33,7 @@ TEST_F(IR_TempTest, id) {
auto* val = b.builder.Temp();
EXPECT_EQ(4u, val->AsId());
val->ToString(str);
val->ToString(str, program->Symbols());
EXPECT_EQ("%4", str.str());
}

View File

@ -21,6 +21,7 @@
#include "gtest/gtest.h"
#include "src/tint/ir/builder_impl.h"
#include "src/tint/ir/disassembler.h"
#include "src/tint/number.h"
#include "src/tint/program_builder.h"
namespace tint::ir {
@ -41,19 +42,29 @@ class TestHelperBase : public BASE, public ProgramBuilder {
if (gen_) {
return *gen_;
}
program = std::make_unique<Program>(std::move(*this));
diag::Formatter formatter;
program = std::make_unique<Program>(std::move(*this));
[&]() { ASSERT_TRUE(program->IsValid()) << formatter.format(program->Diagnostics()); }();
gen_ = std::make_unique<BuilderImpl>(program.get());
return *gen_;
}
/// Injects a flow block into the builder
/// @returns the injected block
ir::Block* InjectFlowBlock() {
auto* block = gen_->builder.CreateBlock();
gen_->current_flow_block = block;
return block;
}
/// Creates a BuilderImpl without an originating program. This is used for testing the
/// expressions which don't require the full builder implementation. The current flow block
/// is initialized with an empty block.
/// @returns the BuilderImpl for testing.
BuilderImpl& CreateEmptyBuilder() {
gen_ = std::make_unique<BuilderImpl>(nullptr);
program = std::make_unique<Program>();
gen_ = std::make_unique<BuilderImpl>(program.get());
gen_->current_flow_block = gen_->builder.CreateBlock();
return *gen_;
}

View File

@ -18,6 +18,7 @@
#include <ostream>
#include "src/tint/castable.h"
#include "src/tint/symbol_table.h"
namespace tint::ir {
@ -35,8 +36,9 @@ class Value : public Castable<Value> {
/// Write the value to the given stream
/// @param out the stream to write to
/// @param st the symbol table
/// @returns the stream
virtual std::ostream& ToString(std::ostream& out) const = 0;
virtual std::ostream& ToString(std::ostream& out, const SymbolTable& st) const = 0;
protected:
/// Constructor