diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt index e158941876..7988364f5c 100644 --- a/src/tint/CMakeLists.txt +++ b/src/tint/CMakeLists.txt @@ -678,6 +678,8 @@ if(${TINT_BUILD_IR}) list(APPEND TINT_LIB_SRCS ir/binary.cc ir/binary.h + ir/bitcast.cc + ir/bitcast.h ir/block.cc ir/block.h ir/builder.cc @@ -1378,6 +1380,7 @@ if(TINT_BUILD_TESTS) if (${TINT_BUILD_IR}) list(APPEND TINT_TEST_SRCS ir/binary_test.cc + ir/bitcast_test.cc ir/builder_impl_test.cc ir/constant_test.cc ir/temp_test.cc diff --git a/src/tint/ir/binary_test.cc b/src/tint/ir/binary_test.cc index d7ea7dd8c9..05d70651ee 100644 --- a/src/tint/ir/binary_test.cc +++ b/src/tint/ir/binary_test.cc @@ -34,6 +34,7 @@ TEST_F(IR_InstructionTest, CreateAnd) { EXPECT_EQ(instr->GetKind(), Binary::Kind::kAnd); ASSERT_TRUE(instr->Result()->Is()); + ASSERT_NE(instr->Result()->Type(), nullptr); EXPECT_EQ(Temp::Id(42), instr->Result()->As()->AsId()); ASSERT_TRUE(instr->LHS()->Is()); @@ -48,7 +49,7 @@ TEST_F(IR_InstructionTest, CreateAnd) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 & 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 & 2"); } TEST_F(IR_InstructionTest, CreateOr) { @@ -75,7 +76,7 @@ TEST_F(IR_InstructionTest, CreateOr) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 | 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 | 2"); } TEST_F(IR_InstructionTest, CreateXor) { @@ -102,14 +103,14 @@ TEST_F(IR_InstructionTest, CreateXor) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 ^ 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 ^ 2"); } TEST_F(IR_InstructionTest, CreateLogicalAnd) { auto& b = CreateEmptyBuilder(); b.builder.next_temp_id = Temp::Id(42); - const auto* instr = b.builder.LogicalAnd(b.builder.ir.types.Get(), + const auto* instr = b.builder.LogicalAnd(b.builder.ir.types.Get(), b.builder.Constant(4_i), b.builder.Constant(2_i)); EXPECT_EQ(instr->GetKind(), Binary::Kind::kLogicalAnd); @@ -129,14 +130,14 @@ TEST_F(IR_InstructionTest, CreateLogicalAnd) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 && 2"); + EXPECT_EQ(str.str(), "%42 (bool) = 4 && 2"); } TEST_F(IR_InstructionTest, CreateLogicalOr) { auto& b = CreateEmptyBuilder(); b.builder.next_temp_id = Temp::Id(42); - const auto* instr = b.builder.LogicalOr(b.builder.ir.types.Get(), + const auto* instr = b.builder.LogicalOr(b.builder.ir.types.Get(), b.builder.Constant(4_i), b.builder.Constant(2_i)); EXPECT_EQ(instr->GetKind(), Binary::Kind::kLogicalOr); @@ -156,7 +157,7 @@ TEST_F(IR_InstructionTest, CreateLogicalOr) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 || 2"); + EXPECT_EQ(str.str(), "%42 (bool) = 4 || 2"); } TEST_F(IR_InstructionTest, CreateEqual) { @@ -183,7 +184,7 @@ TEST_F(IR_InstructionTest, CreateEqual) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 == 2"); + EXPECT_EQ(str.str(), "%42 (bool) = 4 == 2"); } TEST_F(IR_InstructionTest, CreateNotEqual) { @@ -210,7 +211,7 @@ TEST_F(IR_InstructionTest, CreateNotEqual) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 != 2"); + EXPECT_EQ(str.str(), "%42 (bool) = 4 != 2"); } TEST_F(IR_InstructionTest, CreateLessThan) { @@ -237,7 +238,7 @@ TEST_F(IR_InstructionTest, CreateLessThan) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 < 2"); + EXPECT_EQ(str.str(), "%42 (bool) = 4 < 2"); } TEST_F(IR_InstructionTest, CreateGreaterThan) { @@ -264,7 +265,7 @@ TEST_F(IR_InstructionTest, CreateGreaterThan) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 > 2"); + EXPECT_EQ(str.str(), "%42 (bool) = 4 > 2"); } TEST_F(IR_InstructionTest, CreateLessThanEqual) { @@ -291,7 +292,7 @@ TEST_F(IR_InstructionTest, CreateLessThanEqual) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 <= 2"); + EXPECT_EQ(str.str(), "%42 (bool) = 4 <= 2"); } TEST_F(IR_InstructionTest, CreateGreaterThanEqual) { @@ -318,7 +319,7 @@ TEST_F(IR_InstructionTest, CreateGreaterThanEqual) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 >= 2"); + EXPECT_EQ(str.str(), "%42 (bool) = 4 >= 2"); } TEST_F(IR_InstructionTest, CreateShiftLeft) { @@ -345,7 +346,7 @@ TEST_F(IR_InstructionTest, CreateShiftLeft) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 << 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 << 2"); } TEST_F(IR_InstructionTest, CreateShiftRight) { @@ -372,7 +373,7 @@ TEST_F(IR_InstructionTest, CreateShiftRight) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 >> 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 >> 2"); } TEST_F(IR_InstructionTest, CreateAdd) { @@ -399,7 +400,7 @@ TEST_F(IR_InstructionTest, CreateAdd) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 + 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 + 2"); } TEST_F(IR_InstructionTest, CreateSubtract) { @@ -426,7 +427,7 @@ TEST_F(IR_InstructionTest, CreateSubtract) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 - 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 - 2"); } TEST_F(IR_InstructionTest, CreateMultiply) { @@ -453,7 +454,7 @@ TEST_F(IR_InstructionTest, CreateMultiply) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 * 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 * 2"); } TEST_F(IR_InstructionTest, CreateDivide) { @@ -480,7 +481,7 @@ TEST_F(IR_InstructionTest, CreateDivide) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 / 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 / 2"); } TEST_F(IR_InstructionTest, CreateModulo) { @@ -507,7 +508,7 @@ TEST_F(IR_InstructionTest, CreateModulo) { std::stringstream str; instr->ToString(str, program->Symbols()); - EXPECT_EQ(str.str(), "%42 = 4 % 2"); + EXPECT_EQ(str.str(), "%42 (i32) = 4 % 2"); } } // namespace diff --git a/src/tint/ir/bitcast.cc b/src/tint/ir/bitcast.cc new file mode 100644 index 0000000000..7ea2b7ff36 --- /dev/null +++ b/src/tint/ir/bitcast.cc @@ -0,0 +1,37 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/tint/ir/bitcast.h" +#include "src/tint/debug.h" + +TINT_INSTANTIATE_TYPEINFO(tint::ir::Bitcast); + +namespace tint::ir { + +Bitcast::Bitcast(const Value* result, const Value* val) : result_(result), val_(val) { + TINT_ASSERT(IR, result_); + TINT_ASSERT(IR, val_); +} + +Bitcast::~Bitcast() = default; + +std::ostream& Bitcast::ToString(std::ostream& out, const SymbolTable& st) const { + Result()->ToString(out, st); + out << " = bitcast("; + val_->ToString(out, st); + out << ")"; + return out; +} + +} // namespace tint::ir diff --git a/src/tint/ir/bitcast.h b/src/tint/ir/bitcast.h new file mode 100644 index 0000000000..56b9651697 --- /dev/null +++ b/src/tint/ir/bitcast.h @@ -0,0 +1,63 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_TINT_IR_BITCAST_H_ +#define SRC_TINT_IR_BITCAST_H_ + +#include + +#include "src/tint/castable.h" +#include "src/tint/ir/instruction.h" +#include "src/tint/ir/value.h" +#include "src/tint/symbol_table.h" +#include "src/tint/type/type.h" + +namespace tint::ir { + +/// A bitcast instruction in the IR. +class Bitcast : public Castable { + public: + /// Constructor + /// @param result the result value + /// @param val the value being bitcast + Bitcast(const Value* result, const Value* val); + Bitcast(const Bitcast& instr) = delete; + Bitcast(Bitcast&& instr) = delete; + ~Bitcast() override; + + Bitcast& operator=(const Bitcast& instr) = delete; + Bitcast& operator=(Bitcast&& instr) = delete; + + /// @returns the result value for the instruction + const Value* Result() const { return result_; } + + /// @returns the left-hand-side value for the instruction + const Value* Val() const { return val_; } + + /// 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 SymbolTable& st) const override; + + private: + const Value* result_ = nullptr; + const Value* val_ = nullptr; +}; + +std::ostream& operator<<(std::ostream& out, const Bitcast&); + +} // namespace tint::ir + +#endif // SRC_TINT_IR_BITCAST_H_ diff --git a/src/tint/ir/bitcast_test.cc b/src/tint/ir/bitcast_test.cc new file mode 100644 index 0000000000..3b5cecdd52 --- /dev/null +++ b/src/tint/ir/bitcast_test.cc @@ -0,0 +1,49 @@ +// Copyright 2023 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "src/tint/ir/instruction.h" +#include "src/tint/ir/test_helper.h" + +namespace tint::ir { +namespace { + +using namespace tint::number_suffixes; // NOLINT + // +using IR_InstructionTest = TestHelper; + +TEST_F(IR_InstructionTest, Bitcast) { + auto& b = CreateEmptyBuilder(); + + b.builder.next_temp_id = Temp::Id(42); + const auto* instr = + b.builder.Bitcast(b.builder.ir.types.Get(), b.builder.Constant(4_i)); + + ASSERT_TRUE(instr->Result()->Is()); + EXPECT_EQ(Temp::Id(42), instr->Result()->As()->AsId()); + ASSERT_NE(instr->Result()->Type(), nullptr); + + ASSERT_TRUE(instr->Val()->Is()); + auto val = instr->Val()->As()->value; + ASSERT_TRUE(val->Is>()); + EXPECT_EQ(4_i, val->As>()->ValueAs()); + + std::stringstream str; + instr->ToString(str, program->Symbols()); + EXPECT_EQ(str.str(), "%42 (i32) = bitcast(4)"); +} + +} // namespace +} // namespace tint::ir diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc index 2c92f8ccd3..ba0ed9e038 100644 --- a/src/tint/ir/builder.cc +++ b/src/tint/ir/builder.cc @@ -178,4 +178,8 @@ const Binary* Builder::Modulo(const type::Type* type, const Value* lhs, const Va return CreateBinary(Binary::Kind::kModulo, type, lhs, rhs); } +const ir::Bitcast* Builder::Bitcast(const type::Type* type, const Value* val) { + return ir.instructions.Create(Temp(type), val); +} + } // namespace tint::ir diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h index 835c8c0532..7f442f2159 100644 --- a/src/tint/ir/builder.h +++ b/src/tint/ir/builder.h @@ -19,6 +19,7 @@ #include "src/tint/constant/scalar.h" #include "src/tint/ir/binary.h" +#include "src/tint/ir/bitcast.h" #include "src/tint/ir/constant.h" #include "src/tint/ir/function.h" #include "src/tint/ir/if.h" @@ -287,6 +288,12 @@ class Builder { /// @returns the operation const Binary* Modulo(const type::Type* type, const Value* lhs, const Value* rhs); + /// Creates a bitcast instruction + /// @param type the result type of the bitcast + /// @param val the value being bitcast + /// @returns the instruction + const ir::Bitcast* Bitcast(const type::Type* type, const Value* val); + /// @returns a unique temp id Temp::Id AllocateTempId(); diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc index 8196f44f6a..115b6d7d79 100644 --- a/src/tint/ir/builder_impl.cc +++ b/src/tint/ir/builder_impl.cc @@ -16,6 +16,7 @@ #include "src/tint/ast/alias.h" #include "src/tint/ast/binary_expression.h" +#include "src/tint/ast/bitcast_expression.h" #include "src/tint/ast/block_statement.h" #include "src/tint/ast/bool_literal_expression.h" #include "src/tint/ast/break_if_statement.h" @@ -522,7 +523,7 @@ utils::Result BuilderImpl::EmitExpression(const ast::Expression* e expr, // [&](const ast::IndexAccessorExpression* a) { return EmitIndexAccessor(a); }, [&](const ast::BinaryExpression* b) { return EmitBinary(b); }, - // [&](const ast::BitcastExpression* b) { return EmitBitcast(b); }, + [&](const ast::BitcastExpression* b) { return EmitBitcast(b); }, // [&](const ast::CallExpression* c) { return EmitCall(c); }, // [&](const ast::IdentifierExpression* i) { return EmitIdentifier(i); }, [&](const ast::LiteralExpression* l) { return EmitLiteral(l); }, @@ -629,6 +630,19 @@ utils::Result BuilderImpl::EmitBinary(const ast::BinaryExpression* return utils::Result(instr->Result()); } +utils::Result BuilderImpl::EmitBitcast(const ast::BitcastExpression* expr) { + auto val = EmitExpression(expr->expr); + if (!val) { + return utils::Failure; + } + + auto* sem = builder.ir.program->Sem().Get(expr); + auto* instr = builder.Bitcast(sem->Type(), val.Get()); + + current_flow_block->instructions.Push(instr); + return utils::Result(instr->Result()); +} + utils::Result BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit) { auto* sem = builder.ir.program->Sem().Get(lit); if (!sem) { diff --git a/src/tint/ir/builder_impl.h b/src/tint/ir/builder_impl.h index 5090be73fe..35476ebeca 100644 --- a/src/tint/ir/builder_impl.h +++ b/src/tint/ir/builder_impl.h @@ -32,6 +32,7 @@ class Program; } // namespace tint namespace tint::ast { class BinaryExpression; +class BitcastExpression; class BlockStatement; class BreakIfStatement; class BreakStatement; @@ -152,6 +153,11 @@ class BuilderImpl { /// @returns the value storing the result if successful, utils::Failure otherwise utils::Result EmitBinary(const ast::BinaryExpression* expr); + /// Emits a bitcast expression + /// @param expr the bitcast expression + /// @returns the value storing the result if successful, utils::Failure otherwise + utils::Result EmitBitcast(const ast::BitcastExpression* expr); + /// Emits a literal expression /// @param lit the literal to emit /// @returns true if successful, false otherwise diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc index 0600a15e4b..41a3f4cdf7 100644 --- a/src/tint/ir/builder_impl_test.cc +++ b/src/tint/ir/builder_impl_test.cc @@ -1437,7 +1437,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) { 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 (u32) = 3 + 4 )"); } @@ -1452,7 +1452,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) { 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 (u32) = 3 - 4 )"); } @@ -1467,7 +1467,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) { 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 (u32) = 3 * 4 )"); } @@ -1482,7 +1482,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) { 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 (u32) = 3 / 4 )"); } @@ -1497,7 +1497,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) { 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 (u32) = 3 % 4 )"); } @@ -1512,7 +1512,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) { 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 (u32) = 3 & 4 )"); } @@ -1527,7 +1527,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) { 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 (u32) = 3 | 4 )"); } @@ -1542,7 +1542,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) { 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 (u32) = 3 ^ 4 )"); } @@ -1557,7 +1557,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block); - EXPECT_EQ(d.AsString(), R"(%1 = true && false + EXPECT_EQ(d.AsString(), R"(%1 (bool) = true && false )"); } @@ -1572,7 +1572,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) { Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block); - EXPECT_EQ(d.AsString(), R"(%1 = false || true + EXPECT_EQ(d.AsString(), R"(%1 (bool) = false || true )"); } @@ -1587,7 +1587,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Equal) { 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 (bool) = 3 == 4 )"); } @@ -1602,7 +1602,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) { 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 (bool) = 3 != 4 )"); } @@ -1617,7 +1617,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) { 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 (bool) = 3 < 4 )"); } @@ -1632,7 +1632,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) { 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 (bool) = 3 > 4 )"); } @@ -1647,7 +1647,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) { 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 (bool) = 3 <= 4 )"); } @@ -1662,7 +1662,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) { 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 (bool) = 3 >= 4 )"); } @@ -1677,7 +1677,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) { 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 (u32) = 3 << 4 )"); } @@ -1692,7 +1692,7 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) { 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 (u32) = 3 >> 4 )"); } @@ -1708,15 +1708,29 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) { 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.3 * 5.5 -%5 = 6.7 / %4 -%6 = 2.5 > %5 -%7 = %3 || %6 + EXPECT_EQ(d.AsString(), R"(%1 (u32) = 3 >> 4 +%2 (u32) = %1 (u32) + 9 +%3 (bool) = 1 < %2 (u32) +%4 (f32) = 2.3 * 5.5 +%5 (f32) = 6.7 / %4 (f32) +%6 (bool) = 2.5 > %5 (f32) +%7 (bool) = %3 (bool) || %6 (bool) )"); } +TEST_F(IR_BuilderImplTest, EmitExpression_Bitcast) { + auto* expr = Bitcast(ty.f32(), 3_u); + WrapInFunction(expr); + + 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 (f32) = bitcast(3) +)"); +} } // namespace } // namespace tint::ir diff --git a/src/tint/ir/temp.cc b/src/tint/ir/temp.cc index 57def51544..e925561895 100644 --- a/src/tint/ir/temp.cc +++ b/src/tint/ir/temp.cc @@ -24,8 +24,8 @@ Temp::Temp(const type::Type* type, Id id) : type_(type), id_(id) {} Temp::~Temp() = default; -std::ostream& Temp::ToString(std::ostream& out, const SymbolTable&) const { - out << "%" << std::to_string(AsId()); +std::ostream& Temp::ToString(std::ostream& out, const SymbolTable& st) const { + out << "%" << std::to_string(AsId()) << " (" << type_->FriendlyName(st) << ")"; return out; } diff --git a/src/tint/ir/temp_test.cc b/src/tint/ir/temp_test.cc index f1fc24f1ec..81a49927a4 100644 --- a/src/tint/ir/temp_test.cc +++ b/src/tint/ir/temp_test.cc @@ -34,7 +34,7 @@ TEST_F(IR_TempTest, id) { EXPECT_EQ(4u, val->AsId()); val->ToString(str, program->Symbols()); - EXPECT_EQ("%4", str.str()); + EXPECT_EQ("%4 (i32)", str.str()); } } // namespace