From 19ebcb22308a7b158a3237f10e46cc48a45352e8 Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Thu, 15 Dec 2022 19:17:22 +0000 Subject: [PATCH] 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 Kokoro: Kokoro Commit-Queue: Dan Sinclair --- src/tint/cmd/main.cc | 4 +- src/tint/ir/binary.cc | 8 +- src/tint/ir/binary.h | 4 +- src/tint/ir/binary_test.cc | 294 +++++++++++++------------ src/tint/ir/builder.h | 56 ++++- src/tint/ir/builder_impl.cc | 43 ++-- src/tint/ir/builder_impl_test.cc | 363 +++++++++++++++++++------------ src/tint/ir/constant.cc | 62 +++--- src/tint/ir/constant.h | 89 +------- src/tint/ir/constant_test.cc | 90 ++++---- src/tint/ir/disassembler.cc | 8 +- src/tint/ir/disassembler.h | 7 +- src/tint/ir/instruction.h | 4 +- src/tint/ir/instruction_test.cc | 36 +-- src/tint/ir/module.h | 7 + src/tint/ir/temp.cc | 2 +- src/tint/ir/temp.h | 4 +- src/tint/ir/temp_test.cc | 2 +- src/tint/ir/test_helper.h | 15 +- src/tint/ir/value.h | 4 +- 20 files changed, 602 insertions(+), 500 deletions(-) diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc index ae2e2e21c8..fd676176e7 100644 --- a/src/tint/cmd/main.cc +++ b/src/tint/cmd/main.cc @@ -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); diff --git a/src/tint/ir/binary.cc b/src/tint/ir/binary.cc index 1a35b614c4..ccb679b736 100644 --- a/src/tint/ir/binary.cc +++ b/src/tint/ir/binary.cc @@ -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; } diff --git a/src/tint/ir/binary.h b/src/tint/ir/binary.h index 755dd9ccf3..0f7fe57958 100644 --- a/src/tint/ir/binary.h +++ b/src/tint/ir/binary.h @@ -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 { /// 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_; diff --git a/src/tint/ir/binary_test.cc b/src/tint/ir/binary_test.cc index 81d0ada2bc..f90661bae0 100644 --- a/src/tint/ir/binary_test.cc +++ b/src/tint/ir/binary_test.cc @@ -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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); 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()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); - auto lhs = instr->LHS()->As(); - ASSERT_TRUE(lhs->IsI32()); - EXPECT_EQ(i32(4), lhs->AsI32()); + auto lhs = instr->LHS()->As()->value; + ASSERT_TRUE(lhs->Is>()); + EXPECT_EQ(4_i, lhs->As>()->ValueAs()); ASSERT_TRUE(instr->RHS()->Is()); - auto rhs = instr->RHS()->As(); - ASSERT_TRUE(rhs->IsI32()); - EXPECT_EQ(i32(2), rhs->AsI32()); + auto rhs = instr->RHS()->As()->value; + ASSERT_TRUE(rhs->Is>()); + EXPECT_EQ(2_i, rhs->As>()->ValueAs()); std::stringstream str; - instr->ToString(str); + instr->ToString(str, program->Symbols()); EXPECT_EQ(str.str(), "%42 = 4 % 2"); } diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h index ceabfa6b31..ca21b8d278 100644 --- a/src/tint/ir/builder.h +++ b/src/tint/ir/builder.h @@ -15,6 +15,9 @@ #ifndef SRC_TINT_IR_BUILDER_H_ #define SRC_TINT_IR_BUILDER_H_ +#include + +#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 + traits::EnableIf, const T>* create(ARGS&&... args) { + return ir.constants.Create(std::forward(args)...); + } + + /// Creates a new ir::Constant /// @param val the constant value /// @returns the new constant - template - const ir::Constant* Constant(T val) { + const ir::Constant* Constant(const constant::Value* val) { return ir.values.Create(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>(ir.types.Get(), 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>(ir.types.Get(), 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>(ir.types.Get(), 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>(ir.types.Get(), 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>(ir.types.Get(), v)); + } + /// Creates a new Temporary /// @returns the new temporary const ir::Temp* Temp() { return ir.values.Create(AllocateTempId()); } diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc index 042a7d5c95..afa56f51d1 100644 --- a/src/tint/ir/builder_impl.cc +++ b/src/tint/ir/builder_impl.cc @@ -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 BuilderImpl::EmitBinary(const ast::BinaryExpression* } utils::Result BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) { - return tint::Switch( // - lit, - [&](const ast::BoolLiteralExpression* l) { - return utils::Result(builder.Constant(l->value)); - }, - [&](const ast::FloatLiteralExpression* l) { - if (l->suffix == ast::FloatLiteralExpression::Suffix::kF) { - return utils::Result( - builder.Constant(f32(static_cast(l->value)))); - } - return utils::Result(builder.Constant(f16(static_cast(l->value)))); - }, - [&](const ast::IntLiteralExpression* l) { - if (l->suffix == ast::IntLiteralExpression::Suffix::kI) { - return utils::Result(builder.Constant(i32(l->value))); - } - return utils::Result(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(builder.Constant(cv)); } bool BuilderImpl::EmitType(const ast::Type* ty) { diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc index 79e6e3feaf..0600a15e4b 100644 --- a/src/tint/ir/builder_impl_test.cc +++ b/src/tint/ir/builder_impl_test.cc @@ -102,9 +102,9 @@ TEST_F(IR_BuilderImplTest, IfStatement) { // Check condition ASSERT_TRUE(flow->condition->Is()); - auto* instr = flow->condition->As(); - ASSERT_TRUE(instr->IsBool()); - EXPECT_TRUE(instr->AsBool()); + auto* instr = flow->condition->As()->value; + ASSERT_TRUE(instr->Is>()); + EXPECT_TRUE(instr->As>()->ValueAs()); } TEST_F(IR_BuilderImplTest, IfStatement_TrueReturns) { @@ -504,9 +504,9 @@ TEST_F(IR_BuilderImplTest, Loop_WithReturn) { // Check condition ASSERT_TRUE(if_flow->condition->Is()); - auto* instr = if_flow->condition->As(); - ASSERT_TRUE(instr->IsBool()); - EXPECT_TRUE(instr->AsBool()); + auto* instr = if_flow->condition->As()->value; + ASSERT_TRUE(instr->Is>()); + EXPECT_TRUE(instr->As>()->ValueAs()); } TEST_F(IR_BuilderImplTest, Loop_WithOnlyReturn) { @@ -950,9 +950,9 @@ TEST_F(IR_BuilderImplTest, While) { // Check condition ASSERT_TRUE(if_flow->condition->Is()); - auto* instr = if_flow->condition->As(); - ASSERT_TRUE(instr->IsBool()); - EXPECT_FALSE(instr->AsBool()); + auto* instr = if_flow->condition->As()->value; + ASSERT_TRUE(instr->Is>()); + EXPECT_FALSE(instr->As>()->ValueAs()); } TEST_F(IR_BuilderImplTest, While_Return) { @@ -1075,9 +1075,9 @@ TEST_F(IR_BuilderImplTest, DISABLED_For) { // Check condition ASSERT_TRUE(if_flow->condition->Is()); - auto* instr = if_flow->condition->As(); - ASSERT_TRUE(instr->IsBool()); - EXPECT_FALSE(instr->AsBool()); + auto* instr = if_flow->condition->As()->value; + ASSERT_TRUE(instr->Is>()); + EXPECT_FALSE(instr->As>()->ValueAs()); } TEST_F(IR_BuilderImplTest, For_NoInitCondOrContinuing) { @@ -1176,9 +1176,9 @@ TEST_F(IR_BuilderImplTest, Switch) { // Check condition ASSERT_TRUE(flow->condition->Is()); - auto* instr = flow->condition->As(); - ASSERT_TRUE(instr->IsI32()); - EXPECT_EQ(1_i, instr->AsI32()); + auto* instr = flow->condition->As()->value; + ASSERT_TRUE(instr->Is>()); + EXPECT_EQ(1_i, instr->As>()->ValueAs()); } 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()); - auto* val = r.Get()->As(); - EXPECT_TRUE(val->IsBool()); - EXPECT_TRUE(val->AsBool()); + auto* val = r.Get()->As()->value; + EXPECT_TRUE(val->Is>()); + EXPECT_TRUE(val->As>()->ValueAs()); } 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()); - auto* val = r.Get()->As(); - EXPECT_TRUE(val->IsBool()); - EXPECT_FALSE(val->AsBool()); + auto* val = r.Get()->As()->value; + EXPECT_TRUE(val->Is>()); + EXPECT_FALSE(val->As>()->ValueAs()); } 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()); - auto* val = r.Get()->As(); - EXPECT_TRUE(val->IsF32()); - EXPECT_EQ(1.2_f, val->AsF32()); + auto* val = r.Get()->As()->value; + EXPECT_TRUE(val->Is>()); + EXPECT_EQ(1.2_f, val->As>()->ValueAs()); } 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()); - auto* val = r.Get()->As(); - EXPECT_TRUE(val->IsF16()); - EXPECT_EQ(1.2_h, val->AsF16()); + auto* val = r.Get()->As()->value; + EXPECT_TRUE(val->Is>()); + EXPECT_EQ(1.2_h, val->As>()->ValueAs()); } 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()); - auto* val = r.Get()->As(); - EXPECT_TRUE(val->IsI32()); - EXPECT_EQ(-2_i, val->AsI32()); + auto* val = r.Get()->As()->value; + EXPECT_TRUE(val->Is>()); + EXPECT_EQ(-2_i, val->As>()->ValueAs()); } 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()); - auto* val = r.Get()->As(); - EXPECT_TRUE(val->IsU32()); - EXPECT_EQ(2_u, val->AsU32()); + auto* val = r.Get()->As()->value; + EXPECT_TRUE(val->Is>()); + EXPECT_EQ(2_u, val->As>()->ValueAs()); } 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 )"); } diff --git a/src/tint/ir/constant.cc b/src/tint/ir/constant.cc index 0138190b51..98a5d3df3a 100644 --- a/src/tint/ir/constant.cc +++ b/src/tint/ir/constant.cc @@ -16,40 +16,48 @@ #include +#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 emit = [&](const constant::Value* c) { + Switch( + c, + [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, + [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, + [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, + [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, + [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, + [&](const constant::Scalar* scalar) { out << scalar->ValueAs().value; }, + [&](const constant::Scalar* scalar) { + out << (scalar->ValueAs() ? "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; } diff --git a/src/tint/ir/constant.h b/src/tint/ir/constant.h index 23eeb02f1d..c5ee079db4 100644 --- a/src/tint/ir/constant.h +++ b/src/tint/ir/constant.h @@ -16,100 +16,29 @@ #define SRC_TINT_IR_CONSTANT_H_ #include -#include +#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 { 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(data_); } - /// @returns the constant data as a `f16`. - /// @note, must only be called if `IsF16()` is true - f16 AsF16() const { return std::get(data_); } - /// @returns the constant data as an `i32`. - /// @note, must only be called if `IsI32()` is true - i32 AsI32() const { return std::get(data_); } - /// @returns the constant data as a `u32`. - /// @note, must only be called if `IsU32()` is true - u32 AsU32() const { return std::get(data_); } - /// @returns the constant data as a `bool`. - /// @note, must only be called if `IsBool()` is true - bool AsBool() const { return std::get(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 data_; + /// The constants value + const constant::Value* const value; }; } // namespace tint::ir diff --git a/src/tint/ir/constant_test.cc b/src/tint/ir/constant_test.cc index b20b4244cc..87eec656a1 100644 --- a/src/tint/ir/constant_test.cc +++ b/src/tint/ir/constant_test.cc @@ -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>()->ValueAs()); - 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>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); } 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>()->ValueAs()); - 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>()); + EXPECT_TRUE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); } 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>()->ValueAs()); - 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>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_TRUE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); } 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>()->ValueAs()); - 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>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_TRUE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); } 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>()->ValueAs()); - 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>()->ValueAs()); - 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>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_FALSE(c->value->Is>()); + EXPECT_TRUE(c->value->Is>()); } } // namespace diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc index d8ee4ba269..37f294cbcb 100644 --- a/src/tint/ir/disassembler.cc +++ b/src/tint/ir/disassembler.cc @@ -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(); diff --git a/src/tint/ir/disassembler.h b/src/tint/ir/disassembler.h index e24524a005..46b4ffdae4 100644 --- a/src/tint/ir/disassembler.h +++ b/src/tint/ir/disassembler.h @@ -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 visited_; std::unordered_set stop_nodes_; diff --git a/src/tint/ir/instruction.h b/src/tint/ir/instruction.h index 8b68465f14..82842ba37a 100644 --- a/src/tint/ir/instruction.h +++ b/src/tint/ir/instruction.h @@ -18,6 +18,7 @@ #include #include "src/tint/castable.h" +#include "src/tint/symbol_table.h" namespace tint::ir { @@ -34,8 +35,9 @@ class Instruction : public Castable { /// 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 diff --git a/src/tint/ir/instruction_test.cc b/src/tint/ir/instruction_test.cc index 08302edbb9..c9307f0f23 100644 --- a/src/tint/ir/instruction_test.cc +++ b/src/tint/ir/instruction_test.cc @@ -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"); } diff --git a/src/tint/ir/module.h b/src/tint/ir/module.h index d95a13e1cc..1ed9ea934e 100644 --- a/src/tint/ir/module.h +++ b/src/tint/ir/module.h @@ -17,9 +17,11 @@ #include +#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 flow_nodes; + /// The constant allocator + utils::BlockAllocator constants; /// The value allocator utils::BlockAllocator 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 diff --git a/src/tint/ir/temp.cc b/src/tint/ir/temp.cc index 30efb86a9d..afd0921265 100644 --- a/src/tint/ir/temp.cc +++ b/src/tint/ir/temp.cc @@ -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; } diff --git a/src/tint/ir/temp.h b/src/tint/ir/temp.h index c621b5c3dd..2db81f3ed8 100644 --- a/src/tint/ir/temp.h +++ b/src/tint/ir/temp.h @@ -18,6 +18,7 @@ #include #include "src/tint/ir/value.h" +#include "src/tint/symbol_table.h" namespace tint::ir { @@ -45,8 +46,9 @@ class Temp : public Castable { /// 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; diff --git a/src/tint/ir/temp_test.cc b/src/tint/ir/temp_test.cc index 1dcae138eb..6b79a51abb 100644 --- a/src/tint/ir/temp_test.cc +++ b/src/tint/ir/temp_test.cc @@ -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()); } diff --git a/src/tint/ir/test_helper.h b/src/tint/ir/test_helper.h index 10694eeb53..e3d66cfcff 100644 --- a/src/tint/ir/test_helper.h +++ b/src/tint/ir/test_helper.h @@ -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(std::move(*this)); diag::Formatter formatter; + + program = std::make_unique(std::move(*this)); [&]() { ASSERT_TRUE(program->IsValid()) << formatter.format(program->Diagnostics()); }(); gen_ = std::make_unique(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(nullptr); + program = std::make_unique(); + gen_ = std::make_unique(program.get()); gen_->current_flow_block = gen_->builder.CreateBlock(); return *gen_; } diff --git a/src/tint/ir/value.h b/src/tint/ir/value.h index 9c41f5225c..6dffc3e596 100644 --- a/src/tint/ir/value.h +++ b/src/tint/ir/value.h @@ -18,6 +18,7 @@ #include #include "src/tint/castable.h" +#include "src/tint/symbol_table.h" namespace tint::ir { @@ -35,8 +36,9 @@ class Value : public Castable { /// 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